神秘的 C++ 线程崩溃
Mysterious C++ threading crash
以下代码在进入 run
函数时奇怪地崩溃了。 None 的 printfs 触发器,单步执行函数会导致崩溃。它是未定义的行为,还是编译器错误?我正在使用 Apple clang 12.0.0 编译 MacOS。它因 EXC_BAD_ACCESS (code = 2)
.
而崩溃
#include <iostream>
#include <thread>
#include <vector>
struct Chunk {
// the array must be this big
// other array sizes don't trigger the bug consistently
uint8_t array[524288];
};
std::thread generator_thread;
std::mutex generator_lock;
std::vector<Chunk*> to_generate;
std::condition_variable data_ready;
std::atomic<bool> running;
void begin();
void run();
void begin() {
running = true;
auto func = [] {
run();
};
generator_thread = std::thread(func);
}
void run() {
printf("Running in generator\n");
while (running) {
printf("Running in loop\n");
Chunk *task;
// take a chunk from the queue
{
std::unique_lock<std::mutex> lock(generator_lock);
data_ready.wait(lock, [] { return to_generate.size() > 0 || !running; });
if (!running) break;
task = to_generate.back();
to_generate.pop_back();
}
printf("deref chunk\n");
// Despite never being executed in this example, this line merely existing
// will cause a crash when entering the run_generator function.
Chunk chunk = *task;
// *task.chunk;
// ^^^ Only having the line above will not trigger the bug; it must be assigned
}
}
int main(int argc, const char *argv[]) {
begin();
while (true) {
printf("run\n");
}
return 0;
}
因此,当您将函数更改为使用 space 为半兆字节的对象预留堆栈帧时……在设置该堆栈帧时它会在函数开始时崩溃?
这可能是因为您使 sizeof Chunk
等于整个默认 OSX 线程堆栈大小 512Kb。如果单步进入该函数,您应该能够看到触发错误的 指令 ,它可能是堆栈帧 setup/function 序言的一部分。
所有这些都是特定于实现的(堆栈帧、每个线程的堆栈大小),但是将非常大的东西放在堆栈上通常不是一个好主意。
以下代码在进入 run
函数时奇怪地崩溃了。 None 的 printfs 触发器,单步执行函数会导致崩溃。它是未定义的行为,还是编译器错误?我正在使用 Apple clang 12.0.0 编译 MacOS。它因 EXC_BAD_ACCESS (code = 2)
.
#include <iostream>
#include <thread>
#include <vector>
struct Chunk {
// the array must be this big
// other array sizes don't trigger the bug consistently
uint8_t array[524288];
};
std::thread generator_thread;
std::mutex generator_lock;
std::vector<Chunk*> to_generate;
std::condition_variable data_ready;
std::atomic<bool> running;
void begin();
void run();
void begin() {
running = true;
auto func = [] {
run();
};
generator_thread = std::thread(func);
}
void run() {
printf("Running in generator\n");
while (running) {
printf("Running in loop\n");
Chunk *task;
// take a chunk from the queue
{
std::unique_lock<std::mutex> lock(generator_lock);
data_ready.wait(lock, [] { return to_generate.size() > 0 || !running; });
if (!running) break;
task = to_generate.back();
to_generate.pop_back();
}
printf("deref chunk\n");
// Despite never being executed in this example, this line merely existing
// will cause a crash when entering the run_generator function.
Chunk chunk = *task;
// *task.chunk;
// ^^^ Only having the line above will not trigger the bug; it must be assigned
}
}
int main(int argc, const char *argv[]) {
begin();
while (true) {
printf("run\n");
}
return 0;
}
因此,当您将函数更改为使用 space 为半兆字节的对象预留堆栈帧时……在设置该堆栈帧时它会在函数开始时崩溃?
这可能是因为您使 sizeof Chunk
等于整个默认 OSX 线程堆栈大小 512Kb。如果单步进入该函数,您应该能够看到触发错误的 指令 ,它可能是堆栈帧 setup/function 序言的一部分。
所有这些都是特定于实现的(堆栈帧、每个线程的堆栈大小),但是将非常大的东西放在堆栈上通常不是一个好主意。