gpt4 book ai didi

c++ - 条件变量和#pragma pack bug

转载 作者:行者123 更新时间:2023-11-28 05:07:43 25 4
gpt4 key购买 nike

我发现这段代码没有按预期工作:

#pragma pack(push, 1)

class myclass {
protected:
bool mycrasher[1]; // with mycrasher[4] it works!
std::mutex mtx;
std::condition_variable cv;

void thread_func() {
std::this_thread::sleep_for(std::chrono::seconds(1));

std::chrono::milliseconds timeout(1000);
std::unique_lock<std::mutex> l(mtx, std::defer_lock);
while (true) {
auto now = std::chrono::system_clock::now();
l.lock();
while (true) {
std::cout << "Waiting..." << std::endl;
auto result = cv.wait_until(l, now + timeout);
std::cout << "Timed out..." << std::endl;
if (result == std::cv_status::timeout)
break;
}
l.unlock();
}
}

public:
myclass() {
std::lock_guard<std::mutex> l(mtx);
std::thread *t = new std::thread(&myclass::thread_func, this);
t->detach();
};

void start() {
std::cout << "myclass started." << std::endl;
std::cout << "sizeof(std::mutex) = " << sizeof(std::mutex) << std::endl;
std::cout << "sizeof(std::condition_variable) = " << sizeof(std::condition_variable) << std::endl;
}
};
#pragma pack(pop)

int main() {
myclass x;
x.start();
std::this_thread::sleep_for(std::chrono::seconds(60));
}

我希望代码在 cv.wait_until 调用上等待一秒钟然后重复,但只是卡在调用上。如果我删除 #pragma 指令,问题(凭直觉)就会消失,因为我正在打包互斥体和 CV。但是,当我运行这段代码时,我得到:

myclass started.
sizeof(std::mutex) = 40
sizeof(std::condition_variable) = 48

有或没有 pragma,所以看来打包并不是真正的问题。

此外,我发现如果我将 mycrasher 变量与 4 字节边界对齐,问题也会消失。同样,如果我在 std::condition_variable cv 声明之后移动变量,问题就会消失,但是当在 std::mutex mtxstd::condition_variable 之间移动时cv 它仍然存在。

当 CV 未正确对齐时,为什么代码段会卡在 cv.wait_until 调用上?预计性能会受到影响,但不会出现明显的停顿。

在 Debian 8 系统上使用 g++ 4.9.2 和 g++ 6.3 复制。

最佳答案

不要使用打包,你不应该对具有互斥锁和条件变量的结构这样做。如果您认为您确实需要它,那么您的方法有问题,因为您通常不应该创建许多这样的对象,也不应该在那里打包。

作为一个简单的解决方法,将您的 mycrasher 放在您的 mtxcv 下方:

#pragma pack(push, 1)
class myclass
{
protected:
std::mutex mtx;
std::condition_variable cv;
bool mycrasher[1];

void thread_func();
public:
myclass();
void start();
};
#pragma pack(pop)

在启用打包的情况下它最有可能无法按预期工作的原因是因为 mtxcv 以奇数地址结束,并且使用它们的一些内部代码具有不同的期待。在某些平台(例如 ARM)上可能会崩溃。

附带说明一下,您的代码不仅存在对齐问题,而且还在 myclass 构造函数内部的堆上泄漏了一个线程对象。

关于c++ - 条件变量和#pragma pack bug,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44279259/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com