c++调试遇到奇怪问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hwdq0012
V2EX    C++

c++调试遇到奇怪问题

  •  
  •   hwdq0012
    nocanstillbb 249 天前 4007 次点击
    这是一个创建于 249 天前的主题,其中的信息可能已经有所发展或是发生改变。
    struct DV_COMMN_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 导致崩溃 随便把它赋值给其他变量就会崩溃

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

    第 1 条附言    248 天前

    解决问题了,来汇报一下

    我自己写的反射是非侵入式的,我把反射的元数据和结构体分为两个头文件 正常在dv_common动态库外是不应该使用元数据的类的, 但由于配置文件是一个大类,没有拆得很清楚, dv_tools里有一个通讯用类也用元数据头文件进行dv_common_config的配置类json序列化了,所以也有特化符号 (正常为了防止冗余,应该只在dv_common里使用反射元数据,是我没设计好

    libdv_tools是一个比较底层的工具动态库,所以我平时都不编译它, 这次在配置文件中加了两个字段 ,没有为dv_tools重新编译特化符号, 又因为dv_tools加载比较早,程序应该是从dv_tools取用旧的反射元数据符号了,导致问题

    #dv_tools 3月14编译的

    root@a3beb7022bce:/repos/dv_app_solution# ll bin/arm64/ -rwxr-xr-x 1 root root 34452552 Apr 11 03:07 libdv_common.so -rwxr-xr-x 1 root root 24991736 Mar 14 02:10 libdv_tools.so 

    #程序模块加载配置

    { "version":"1.0.0.0", "plugins":[ "prism_qt_core", "prism_qt_ui", "dv_tools", //在dv_common之前加载 "dv_common", "dv_algorithm", "dv_camera" ], "openGLVersion":"default", "usingGUI":true } 

    重新编译 dv_tools后部署后就正常了
    下周再重构一下,把dv_common_config的序列化放到dv_common里,向外导出

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

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


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


    @yuzii 桌面软件的动态库,一起编译的,只在桌面 app 上用,所以应该不是 abi 问题,像是内存问题
    lixile
        16
    lixile  
       249 天前
    asan 扫过了
    那 ubsan 扫过了么
    如果调用方有多线程 tsan 扫过了么
    hwdq0012
        17
    hwdq0012  
    OP
       249 天前
    @jujusama model 没有实现移动构造,这里会退化为引用,不是这的问题, 断点才走到这行,还没 step 到 move 里
    hwdq0012
        18
    hwdq0012  
    OP
       249 天前
    @lixile 嗯,调了一下没什么头绪, 试试后面这两个, 这下倒是把交叉编译的调试摸索门清了,谢谢佬
    yanlx
        19
    yanlx  
       249 天前
    https://godbolt.org/z/WeqKM6qr3
    做了个最小例子,看起来各家编译器编译结果都没啥问题。还是 DV_COMMON_EXPORT 和 from_jsonStr 嫌疑比较大。
    另外你的 gdb 里面 ref_image_path 看起来也不对劲。
    bfjm
        20
    bfjm  
       249 天前 via iPhone
    多线程问题吧 这块内存已经被破坏掉了
    exch4nge
        21
    exch4nge  
       249 天前
    gdb 显示的信息里 address 是 prism::json::fromJsonString<dv_common_config>
    所以 dv_common_config 是什么?是 product_config 吗?
    hwdq0012
        22
    hwdq0012  
    OP
       249 天前
    @exch4nge dv_common_config 是 product_config 的父类
    有个字段 std::shared_ptr<product_config> productCOnfig= std::make_shared<product_config>();



    @yanlx 周末再,我一般周末才用 mac ,mac 在 godbolt 的 vim 模式下 ctrl+w 不会关掉 web 标签,windows 老忘记就关掉了
    hwdq0012
        23
    hwdq0012  
    OP
       249 天前
    @ysc3839 #6 还没执行到 from_jsonStr ,make_unique 出来就有问题了
    geelaw
        24
    geelaw  
       249 天前
    @hwdq0012 #22 代码里 product_config 没有基类。

    楼主的代码疑点很多,比如 const && 是无法被移走的,几乎所有代码里 const && 都是错误。

    @GeruzoniAnsasu #14 std::move 并不会导致对象变化,因为只是 static_cast 到 rvalue reference 而已。
    被移动过的 std::string 依然处于有效状态,调试器显示 rpicam_pixel_type 是 address 0 length positive 所以那个位置是无效状态,因此必然存在 bug ,而且并不是由正常的移动构造引起的。
    cxiaobao
        25
    cxiaobao  
       249 天前
    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 ~~~~~~~~~~~~~~ model 是移动语义进入 from_jsonStr 方法的,如果 from_jsonStr 取走了数据所有权,model 会被清空
    1023 return model;
    ~~~~~~~~~ 这里不应该返回 model ,因为 model 可能已经被清空了,
    通常,from_jsonStr 应该返回一个对象,这个对象取得了原本 model 中的数据,应该考虑返回这个对象
    1024 }
    liberize
        26
    liberize  
       248 天前 via Android
    检查一下这个头文件是不是有 2 个不同的版本
    hwdq0012
        27
    hwdq0012  
    OP
       248 天前
    @liberize 检查过了,全盘 find |grep 只有一个源码目录和一个安装目录,vimdiff 看了是一样的


    @cxiaobao 应该不是这个问题,这里只是 make_unique 一个局部变量,还没执行到 Move 那一行


    @geelaw 是的,我怀疑是链接之类的 bug ,但我已经把 Build 目录铲掉重编译了还是这样


    @bfjm 局部变量 make_unique 后构建后就初始化有问题,应该和多线程没关系,和 move 也没关系
    hwdq0012
        28
    hwdq0012  
    OP
       248 天前
    lixile
        29
    lixile  
       245 天前
    `dv_tools 里有一个通讯用类也用元数据头文件进行 dv_common_config 的配置类 json 序列化了`
    我不知道我有没有理解错 居然没有用 cmake 之类的 对这个配置文件 作为 dv_tools 的依赖项么 这样只要配置文件发生变更 就会自动增量重新编译
    还是说这几个项目没有关联在一起 而是独立的 repo 且没有用一个 cmake 工程整体管理?
    @hwdq0012
    hwdq0012
        30
    hwdq0012  
    OP
       245 天前
    @lixile 有个 cmake option ,我之前设置为 off 了,
    我设计的这个框架每个模块都有一个 option 控制编译,安装,部署到 app 目录,都是动态 库,app 只是一个壳
    hwdq0012
        31
    hwdq0012  
    OP
       245 天前
    @lixile 即是独立的 cmake 模块,也是独立的 git repo
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1067 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 18:11 PVG 02:11 LAX 10:11 JFK 13:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86