Valgrind:使用atomic :: compare_exchange_weak时,条件跳转或移动取决于未初始化的值

馊主意

我有一个任务来实现一个非常基本的无锁排序向量(仅具有插入和索引功能),并且一切正常,但是,valgrind表示我有条件地跳转/移动,具体取决于未初始化的值。我使用的是--track-origins = yes,但是我发现这并不是很有帮助。

这是我的索引运算符的代码:

int operator[](int pos) {
    Pair pdata_old = pdata.load();
    Pair pdata_new = pdata_old;

    // Increment ref count
    do {
        pdata_new = pdata_old;
        ++pdata_new.ref_count;
    } while (!pdata.compare_exchange_weak(pdata_old, pdata_new));

    // Get old data
    int ret_val = (*pdata_new.pointer)[pos];

    pdata_old = pdata.load();

    // Decrement ref count
    do {
        pdata_new = pdata_old;
        --pdata_new.ref_count;
        // assert(pdata_new.ref_count >= 0);
    } while (!pdata.compare_exchange_weak(pdata_old, pdata_new));

    return ret_val;
}

Pair只是一个包含vector *和int的结构,构造函数初始化其所有值。我找不到任何依赖未初始化数据的地方,至少仅通过查看我的代码即可。

这是相关的valgrind输出(第121行是在其上声明函数的行,第130和142是compare_exchange_weak()行):

==21299==
==21299== Thread 2:
==21299== Conditional jump or move depends on uninitialised value(s)
==21299==    at 0x10A5C2: LFSV::operator[](int) (lfsv.h:130)
==21299==    by 0x1099F4: read_position_0() (driver.cpp:27)
==21299==    by 0x10FCC6: void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) (invoke.h:60)
==21299==    by 0x10FC5C: std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) (invoke.h:95)
==21299==    by 0x10FC34: _ZNSt6thread8_InvokerISt5tupleIJPFvvEEEE9_M_invokeIJLm0EEEEDTclsr3stdE8__invokespcl10_S_declvalIXT_EEEEESt12_Index_tupleIJXspT_EEE (thread:234)
==21299==    by 0x10FC04: std::thread::_Invoker<std::tuple<void (*)()> >::operator()() (thread:243)
==21299==    by 0x10FAE8: std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() (thread:186)
==21299==    by 0x50FAB9E: execute_native_thread_routine (thread.cc:83)
==21299==    by 0x593208B: start_thread (in /usr/lib/libpthread-2.26.so)
==21299==    by 0x5C3EE7E: clone (in /usr/lib/libc-2.26.so)
==21299==  Uninitialised value was created by a stack allocation
==21299==    at 0x10A520: LFSV::operator[](int) (lfsv.h:121)
==21299==
==21299== Conditional jump or move depends on uninitialised value(s)
==21299==    at 0x10A654: LFSV::operator[](int) (lfsv.h:142)
==21299==    by 0x1099F4: read_position_0() (driver.cpp:27)
==21299==    by 0x10FCC6: void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) (invoke.h:60)
==21299==    by 0x10FC5C: std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) (invoke.h:95)
==21299==    by 0x10FC34: _ZNSt6thread8_InvokerISt5tupleIJPFvvEEEE9_M_invokeIJLm0EEEEDTclsr3stdE8__invokespcl10_S_declvalIXT_EEEEESt12_Index_tupleIJXspT_EEE (thread:234)
==21299==    by 0x10FC04: std::thread::_Invoker<std::tuple<void (*)()> >::operator()() (thread:243)
==21299==    by 0x10FAE8: std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() (thread:186)
==21299==    by 0x50FAB9E: execute_native_thread_routine (thread.cc:83)
==21299==    by 0x593208B: start_thread (in /usr/lib/libpthread-2.26.so)
==21299==    by 0x5C3EE7E: clone (in /usr/lib/libc-2.26.so)
==21299==  Uninitialised value was created by a stack allocation
==21299==    at 0x10A520: LFSV::operator[](int) (lfsv.h:121)
==21299==
彼得·科德斯

compare_exchange_weak在带padding的对象上使用时这是正常现象,无需担心这可能会导致伪造的CAS故障,因此请担心是否compare_exchange_strong使用一次而没有重试循环等。


Pair只是一个包含vector *和int的结构

因此,对普通的64位C ++实现(其中sizeof(vector*) == 8sizeof(int) == 4和)进行了填充alignof(vector*) == 8

为了使每个指针成员8字节对齐,需要将整个struct / class对齐8,因此必须将其大小填充为8的倍数,以便一个数组Pair foo[]正常工作,每个数组元素具有8字节对齐。

但是compare_exchange_weak比较整个对象的位模式,包括填充。

大概你不优化编译,编译器做代码存储当地人堆栈与4字节存储的int成员,但随后将其加载回整Pair2个8字节的负载为X86-64的cmpxchg16b指令,或者(如果atomic<Pair>ISN (不是无锁)进行锁定并有效地执行memcmp

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Valgrind:使用哈希函数时,条件跳转或移动取决于未初始化的值

条件跳转或移动取决于使用valgrind的未初始化值

Valgrind 消息:条件跳转或移动取决于未解析的未初始化值

fread() 导致 Valgrind 错误:“条件跳转或移动取决于未初始化的值”

查明“条件跳转或移动取决于未初始化的值” valgrind消息

错误:条件跳转或移动取决于未初始化的值-C valgrind

Valgrind + C:条件跳转或移动取决于未初始化的值

Valgrind:条件跳转或移动取决于未初始化的值-打开文件

CPP中的Valgrind和内存泄漏:“有条件的跳转或移动取决于未初始化的值”

二进制搜索树,Valgrind条件跳转或移动取决于未初始化的值

Valgrind:libnvidia-glcore.so.346.47条件跳转或移动取决于未初始化的值

条件跳转或移动取决于未初始化的值

如何解决“有条件的跳跃或移动取决于未初始化的值” valgrind错误而导致的strlen错误?

释放字符时,“有条件的跳转或移动取决于未初始化的值”

Valgrind:条件跳转,未初始化的值,C ++基本代码

条件跳转或移动取决于未初始化的值strcat

条件跳转或移动取决于std :: wistringstream的未初始化值

C ++中的动态数组-条件跳转或移动取决于未初始化的值

条件跳转或移动取决于 for 循环中带有 strcat 的未初始化值

如何修复C中的“条件跳转或移动取决于未初始化的值”错误

条件跳转或移动取决于 strcpy 处的未初始化值

Valgrind 使用未初始化的值和无效读取

Valgrind 报告 SIGSEGV 和未初始化值的使用

使用getline()函数的Valgrind未初始化的值错误

C - 链表 valgrind 未初始化错误取决于添加元素的顺序

有条件的跳转或移动取决于未初始化的值和无效的大小写

未初始化条件Valgrind

Valgrind:未初始化的值

为什么RSA_generate_key使用未初始化的值(根据valgrind)