【c++ debug】记一次protobuf结构相关的coredump问题

2024-02-18 23:52

本文主要是介绍【c++ debug】记一次protobuf结构相关的coredump问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

        • 1. 问题现象
        • 2. 问题描述
        • 3. 问题分析
        • 4. 问题根因
        • 5. 问题修复
        • 6. 补充:类成员变量定义为引用类型

1. 问题现象
  • 其中curr_lanes是一个目标上一帧的当前车道current_lanes_
  • curr_lane是lane_id对应的LaneInfo信息
  • 现象:在lane_info->lane().successor_id_size()或lane_info->lane().successor_id().size()为1的情况下,通过for循环去访问lane_info->lane().successor_id()的时候出现了coredump
2. 问题描述
  • (1) 问题必现,问题现象自相矛盾。size为1但是却无法访问,按理来说如果可迭代对象使用for循环访问,为空的情况是不会出问题的,for循环就跳过了

  • (2) 类Lane_info的结构,其中Lane是protobuf结构,如下

    class LaneInfo {const Lane &lane_;		// 所包含的lane的信息, 居然定义的是引用{id_;length_;type_;turn_;successor_ids_;predecessor_ids_;};points;unit_directions_;segments_;total_length_;road_id;};
    
3. 问题分析
  • (1)怀疑Lane的proto实例创建时add_successor_id没有添加成功
    • 检查发现添加方式没有问题,从地图收到的successor_id也不为空,正常填写的
  • (2)怀疑LaneInfo实例没有创建成功
    • 添加打印发现,LaneInfo创建过程未出现失败
  • (3)怀疑是智能指针引用问题
    • std::shared_ptr指针指向内容被异常释放,检查下来也没发现
  • (4)怀疑是引用的原变量已经不在了,仍然尝试去访问
    • 检查发现就是这个原因。LaneInfo类中的&lane_引用很关键
4. 问题根因
  • 满足地图更新条件时,上一次的map_结果会被清理(智能指针管理);但是目标上一帧的current_lanes(类型是LaneInfo)仍去索引lane_信息
  • 问题发生过程
    • (1) 第一次地图更新时,创建了static_map_->hdmap_->{map_, lanes_}的关联关系。其中lanes_结构:<lane_id, LaneInfo>
    • (2)目标第一帧的current_lanes根据static_map_记录了当时的<lane_id, LaneInfo>信息,且由于是proto结构,LaneInfo中copy了&lane_的信息,对应的proto字段bit均已赋值,比如has_successor_id字段、succcessor_id_size字段等;本次访问没问题
    • (3)第二次更新地图时,static_map_关联到了新的hdmap_,即static_map_->new_hdmap_->{map_, lanes_}的关联关系,此时lanes信息已完全变更
    • (4)目标第二帧再去访问第一帧的current_lanes_发现lane proto的successor_id_size有效但是去访问successor_id的时候却找不到原变量,因此失败。即被引用对象已被删除
5. 问题修复
  • (1)static_map_全程只关联一个hdmap_,每次地图更新也只更新该hdmap_。这里的static_map_是一个伪静态类
  • (2)static_map_->hdmap->{map_, lanes_}中的lanes_不做清理,避免重复构建相同lane的LaneInfo,也避免在查询目标前后继车道的过程中出现异常,如目标已记录的successor_id在已更新的地图lanes_中却找不到
6. 补充:类成员变量定义为引用类型
  • (1)C++初始化包括声明时即定义,或者在初始化列表中进行初始化。构造函数分为初始化列表和函数体
  • (2)C++类成员变量定义为引用类型,不能用默认函数初始化,必须定义构造函数来初始化引用成员变量,否则会报引用未初始化错误
  • (3)构造函数的形参也必须是引用类型,如LaneInfo(const Lane& lane) : lane_(lane) {}
    防止引用绑定内存错误,在构造函数结束后所指向内存生命周期已结束,会有问题
  • (4)不能在构造函数里初始化,必须在初始化列表中进行初始化
  • (5)初始化后的引用变量所占用的内存空间和普通变量相同,可通过类的大小进行测试

 


【参考文章】
[1]. c++之类内定义引用成员
[2]. 引用变量所占用的内存空间
[3]. C++类成员变量定义为引用

created by shuaixio, 2024.02.18

这篇关于【c++ debug】记一次protobuf结构相关的coredump问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/722858

相关文章

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

Kotlin Map映射转换问题小结

《KotlinMap映射转换问题小结》文章介绍了Kotlin集合转换的多种方法,包括map(一对一转换)、mapIndexed(带索引)、mapNotNull(过滤null)、mapKeys/map... 目录Kotlin 集合转换:map、mapIndexed、mapNotNull、mapKeys、map

nginx中端口无权限的问题解决

《nginx中端口无权限的问题解决》当Nginx日志报错bind()to80failed(13:Permissiondenied)时,这通常是由于权限不足导致Nginx无法绑定到80端口,下面就来... 目录一、问题原因分析二、解决方案1. 以 root 权限运行 Nginx(不推荐)2. 为 Nginx

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件