c++调试遇到奇怪问题

167 天前
 hwdq0012
struct DV_COMMON_EXPORT product_config {


    int detect_delay_ms = 0;


    int reject_delay_ms = 0;

    int detect_count_oneshot = 1;
    int detect_count = 0;

    int detect_count_interval = 100;
    std::string ref_image_path = "1";

    int cam_x =2;
    int cam_y =3;


    // yuv420p",rgb888
    std::string rpicam_pixel_type = "yuv420p";

    int tmp =44;
};

调试时发现从第一个字符串往后,字段都没有正常初始化

(gdb) info line
Line 1021 of "/repos/dv_app_solution/prism_all/prism/include/prism/prismJson.hpp"
   starts at address 0x7fffeb60f470 <prism::json::fromJsonString<dv_common_config>(std::string const&&)+28>
   and ends at 0x7fffeb60f478 <prism::json::fromJsonString<dv_common_config>(std::string const&&)+36>.
(gdb) list
1016	
1017	template <class T>
1018	static inline std::unique_ptr<T> fromJsonString(const std::string&& str)
1019	{
1020	    std::unique_ptr<T> model = std::make_unique<T>();
1021	    privates::jsonType<T>::type::from_jsonStr(std::move(*model), std::move(str), 0, static_cast<int>(str.length() - 1));
1022	
1023	    return model;
1024	}
1025	template <class T>
(gdb) print *model
$9 = {detect_delay_ms = 0, reject_delay_ms = 0, detect_count_oneshot = 1, detect_count = 0, detect_count_interval = 100, ref_image_path = "", cam_x = 0, 
  cam_y = 0, rpicam_pixel_type = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>, tmp = 796092265}
(gdb) 

程序会在后面的逻辑中,崩溃在使用 rpicam_pixel_type 这个字段的时候,用 asan 看了是由于这个错误的字符串被认为超过 10 个 T 导致崩溃 随便把它赋值给其他变量就会崩溃

没有思路,有什么方式进一进定位吗

3495 次点击
所在节点    C++
31 条回复
billlee
166 天前
DV_COMMON_EXPORT 是什么?
shapper
166 天前
DV_COMMON_EXPORT 估计是到处宏;
如果导出的模块,结构的所有 std::string 全部要改成 char*,不然以后跨模块,有得你受咯
yanlx
166 天前
用 gbd watch 看变量在哪里被修改了。
yanlx
166 天前
@yanlx edit:gdb watch
OBJECTION
166 天前
丢给 gpt 阔以直接问出来啊。fromJsonString 这玩意是直接内存拷贝啊。。string 是类啊。。关键其实不在于你上面的定义。。 而是感觉你 guide 看漏了。。
ysc3839
166 天前
from_jsonStr 的代码呢?
yolee599
166 天前
有点看不懂,现在的 c++ 已经可以在定义结构体的时候赋值了吗?建议贴代码出来
geligaoli
166 天前
2 楼说的对,如果是 export 的,不要使用 c++类,只使用基本数据类型,你无法知道调用者用的是哪种 stl 的实现和内存分配,不一致就会出现莫名其妙的错误。
ksedz
166 天前
是不是因为你给了短字符串,编译器错误优化到了栈上?
cnbatch
166 天前
jujusama
166 天前
```cpp
std::unique_ptr<T> model = std::make_unique<T>();
func(std::move(*model));
return model;
```

这 model 不是被 move 了吗?这是在干嘛
yuzii
166 天前
导出动态库、std::string 、内存分配问题
这 3 个结合大概率是 c++ abi 混用引起的吧
codyfeng
166 天前
@jujusama 说的对,model 里面的 std::string 已经 move 了。去掉 std::move()试试。
GeruzoniAnsasu
166 天前
fromJsonString 的入参是右值引用,会调用对象的移动构造
你的 product_config 没有 explict 的移动构造,那么会根据内部成员的移动构造生成隐式移动构造
调用完移动构造后 std::string 会变为无效状态


在你这个地方报错显示 std::string 成员的指针已经变成了 null ,说明之前被移动过了,合理推测是你使用了类似
product_config c;
a = fromJsonString(c);
b = fromJsonString(c);
的代码
hwdq0012
166 天前
@GeruzoniAnsasu
@jujusama
我断点在 make_unique 的那一行,hit 后 next 执行一步,那时在 gdb 里 print *model ,就已经是这样了,应该不是移动构造导致的,因为单元测试过嵌套类
再者,是第一个字符串后面的 int 也有问题了, 前面的 Int 没有问题


@yuzii 桌面软件的动态库,一起编译的,只在桌面 app 上用,所以应该不是 abi 问题,像是内存问题
lixile
166 天前
asan 扫过了
那 ubsan 扫过了么
如果调用方有多线程 tsan 扫过了么
hwdq0012
166 天前
@jujusama model 没有实现移动构造,这里会退化为引用,不是这的问题, 断点才走到这行,还没 step 到 move 里
hwdq0012
166 天前
@lixile 嗯,调了一下没什么头绪, 试试后面这两个, 这下倒是把交叉编译的调试摸索门清了,谢谢佬
yanlx
166 天前
https://godbolt.org/z/WeqKM6qr3
做了个最小例子,看起来各家编译器编译结果都没啥问题。还是 DV_COMMON_EXPORT 和 from_jsonStr 嫌疑比较大。
另外你的 gdb 里面 ref_image_path 看起来也不对劲。
bfjm
166 天前
多线程问题吧 这块内存已经被破坏掉了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1124436

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX