C++11:在多线程程序中使用局部静态变量导致 coredump
Posted
技术标签:
【中文标题】C++11:在多线程程序中使用局部静态变量导致 coredump【英文标题】:C++11 : Using local static variables in multithreaded program caused coredump 【发布时间】:2021-12-28 06:55:49 【问题描述】:在C++11中,我创建了100个线程,每个线程调用Test::PushFunc,添加局部静态变量index,插入到局部集合变量本地地图。
理论上,index存储在Initialized Data Segment Memory中,并在程序运行时由每个线程添加。 下面一行
assert(it == localMap.end());
是合理的,因为 index 插入到 localMap 中不会重复。
但实际上,程序在断言中是随机转储的。你能告诉我为什么吗?谢谢。
#include <set>
#include <iostream>
#include <thread>
class Test
public:
std::set<std::string> localMap;
void PushFunc()
static uint64_t index = 0;
while (true)
std::cout << "index : " << index << "\n";
++index;
const auto& s = std::to_string(index);
const auto& it = localMap.find(s);
assert(it == localMap.end()); //! coredump here
localMap.insert(s);
if (index > 20000000)
break;
;
int main ()
std::vector<std::thread> processThreads;
for (int i = 0; i < 100; ++i)
processThreads.emplace_back(
std::thread([]()
Test t;
t.PushFunc();
));
for(auto& thread : processThreads)
thread.join();
【问题讨论】:
为什么是const auto&
?
@ÖöTiib localMap
不在线程之间共享,只有 index
是。
为什么不能const auto&
?每个变量都不会改变可以定义为const
【参考方案1】:
但实际上,程序在断言中是随机转储的。你能告诉我为什么吗?
因为你有一个数据竞争——多个线程试图在没有任何同步的情况下读取和写入同一个变量。
index
是一个全局 变量。您需要使用互斥锁来保护对它的访问。
日期:
但localMap不是全局变量,数据竞争无法解释一个索引重复两次。
-
具有数据竞争(未定义行为)的程序可以产生任何结果。
是的,可以。
考虑以下指令交错(时间递减):
T1 将index
加载到寄存器中(比如5
)。
T2 加载index
(再次5
)
T1 将 index
递增到 6
,将 "6"
存储到其映射中
T1 加载 6
,将 index
递增到 7
,将 "7"
存储到其映射中
T2“增量”索引到6
,将"6"
存储到自己的地图中
T1 加载 6
,将其增加到 7
,尝试将 "7"
存储到其映射中 ==> 断言失败!
问题在于index++
不是原子 操作,并且(没有互斥体)其他线程可能会干扰它。
【讨论】:
但是localMap
不是全局变量,数据竞争无法解释一个index
重复两次。
@ArmStrong 你错了。我已经更新了答案。
@ArmStrong 您正在通过++index
在多个线程中更新index
。一个线程可以多次观察到相同的值(最多2500次)。
@EmployedRussian 非常感谢。你的解释很清楚。以上是关于C++11:在多线程程序中使用局部静态变量导致 coredump的主要内容,如果未能解决你的问题,请参考以下文章