神秘的 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 序言的一部分。

所有这些都是特定于实现的(堆栈帧、每个线程的堆栈大小),但是将非常大的东西放在堆栈上通常不是一个好主意。