V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hwdq0012
V2EX  ›  C++

c++调试遇到奇怪问题

  •  
  •   hwdq0012 ·
    nocanstillbb · 14 天前 · 2146 次点击
    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 导致崩溃 随便把它赋值给其他变量就会崩溃

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

    第 1 条附言  ·  13 天前

    解决问题了,来汇报一下

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

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


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


    @yuzii 桌面软件的动态库,一起编译的,只在桌面 app 上用,所以应该不是 abi 问题,像是内存问题
    lixile
        16
    lixile  
       14 天前
    asan 扫过了
    那 ubsan 扫过了么
    如果调用方有多线程 tsan 扫过了么
    hwdq0012
        17
    hwdq0012  
    OP
       14 天前
    @jujusama model 没有实现移动构造,这里会退化为引用,不是这的问题, 断点才走到这行,还没 step 到 move 里
    hwdq0012
        18
    hwdq0012  
    OP
       14 天前
    @lixile 嗯,调了一下没什么头绪, 试试后面这两个, 这下倒是把交叉编译的调试摸索门清了,谢谢佬
    yanlx
        19
    yanlx  
       14 天前
    https://godbolt.org/z/WeqKM6qr3
    做了个最小例子,看起来各家编译器编译结果都没啥问题。还是 DV_COMMON_EXPORT 和 from_jsonStr 嫌疑比较大。
    另外你的 gdb 里面 ref_image_path 看起来也不对劲。
    bfjm
        20
    bfjm  
       14 天前 via iPhone
    多线程问题吧 这块内存已经被破坏掉了
    exch4nge
        21
    exch4nge  
       14 天前
    gdb 显示的信息里 address 是 prism::json::fromJsonString<dv_common_config>
    所以 dv_common_config 是什么?是 product_config 吗?
    hwdq0012
        22
    hwdq0012  
    OP
       14 天前
    @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
       14 天前
    @ysc3839 #6 还没执行到 from_jsonStr ,make_unique 出来就有问题了
    geelaw
        24
    geelaw  
       14 天前
    @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  
       14 天前
    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  
       13 天前 via Android
    检查一下这个头文件是不是有 2 个不同的版本
    hwdq0012
        27
    hwdq0012  
    OP
       13 天前
    @liberize 检查过了,全盘 find |grep 只有一个源码目录和一个安装目录,vimdiff 看了是一样的


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


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


    @bfjm 局部变量 make_unique 后构建后就初始化有问题,应该和多线程没关系,和 move 也没关系
    hwdq0012
        28
    hwdq0012  
    OP
       13 天前
    lixile
        29
    lixile  
       10 天前
    `dv_tools 里有一个通讯用类也用元数据头文件进行 dv_common_config 的配置类 json 序列化了`
    我不知道我有没有理解错 居然没有用 cmake 之类的 对这个配置文件 作为 dv_tools 的依赖项么 这样只要配置文件发生变更 就会自动增量重新编译
    还是说这几个项目没有关联在一起 而是独立的 repo 且没有用一个 cmake 工程整体管理?
    @hwdq0012
    hwdq0012
        30
    hwdq0012  
    OP
       10 天前
    @lixile 有个 cmake option ,我之前设置为 off 了,
    我设计的这个框架每个模块都有一个 option 控制编译,安装,部署到 app 目录,都是动态 库,app 只是一个壳
    hwdq0012
        31
    hwdq0012  
    OP
       10 天前
    @lixile 即是独立的 cmake 模块,也是独立的 git repo
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4000 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:58 · PVG 08:58 · LAX 17:58 · JFK 20:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.