gpt4 book ai didi

c++ - 工作线程在 DLL(但不是 .exe)中的静态对象被破坏之前被强制终止?

转载 作者:行者123 更新时间:2023-11-30 05:16:43 26 4
gpt4 key购买 nike

考虑以下代码。以下所有内容均使用 v140 C++ 运行时在 Visual Studio 2015 中编译和执行:

#include <thread>
#include <atomic>
#include <sstream>

#include <Windows.h>

struct StaticThreadTest
{
~StaticThreadTest()
{
_terminationRequested = true;
if (_thread.joinable())
_thread.join();

std::ostringstream ss;
ss << "Thread finished gracefully: " << _threadFinishedGracefully << "\n";
OutputDebugStringA(ss.str().c_str());
}

void startThread()
{
_thread = std::thread([&]() {
while (!_terminationRequested);

_threadFinishedGracefully = true;
});
}

std::thread _thread;
std::atomic<bool> _terminationRequested {false};
std::atomic<bool> _threadFinishedGracefully {false};
};

static StaticThreadTest thread;

int main()
{
thread.startThread();

return 0;
}

它按预期工作 - 打印“Thread finished gracefully: 1”并退出应用程序。

但是,如果我将此代码移动到 DLL(创建一个空 DLL,从中导出一个函数,将 StaticThreadTest 对象放在 dll 的 .cpp 中,调用 thread.startThread( ) 并从 main.cpp 调用此导出函数),代码有时会打印“Thread finished gracefully: 0”,但更多时候它只是卡在 thread.join().

是否记录了此行为?这是运行时中的错误还是有意为之?

注意:即使在 main.cpp(在 exe 中)中,使用 v120 工具集编译的相同代码也会在 100% 的时间内挂起。似乎 v120 工具集中存在错误,而在 v140 中它已针对 .exe 修复,但未针对 .dll 修复。

最佳答案

似乎使用不同的同步机制而不是繁忙的循环(std::mutex + std::condition_variable)可以消除这种情况。

以下示例演示了这两种机制:

#include "thread-test-dll.h"

#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
//#define _BUSY_WAIT
#ifdef _BUSY_WAIT
#include <atomic>
#endif

class foo
{
public:
foo()
#ifdef _BUSY_WAIT
: termination_requested_(false),
terminated_gracefully_(false)
#endif
{
std::cout << "foo::foo()...\n";
}

void run()
{
#define _USE_LAMBDA
#ifdef _USE_LAMBDA
thread_ = std::thread([&]() {
work();
});
#else
thread_ = std::thread(&foo::work, this);
#endif
}

~foo()
{
std::cout << "foo::~foo()...\n";
if (thread_.joinable())
{
#ifdef _BUSY_WAIT
termination_requested_ = true;
#else
condition_variable_.notify_all();
#endif
thread_.join();
std::cout << "thread joined...\n";
}
else
{
std::cout << "thread was not joinable...\n";
}
#ifdef _BUSY_WAIT
std::cout << "terminated_gracefully_ = " << terminated_gracefully_ << "\n";
#endif
}

void work()
{
#ifdef _BUSY_WAIT
while (!termination_requested_);
terminated_gracefully_ = true;
#else
std::unique_lock<std::mutex> mutex_lock(mutex_);
condition_variable_.wait(mutex_lock);
#endif
std::cout << "foo:work() terminating...\n";
}

private:
#ifdef _BUSY_WAIT
std::atomic<bool> termination_requested_;
std::atomic<bool> terminated_gracefully_;
#endif
std::thread thread_;
std::mutex mutex_;
std::condition_variable condition_variable_;
};

static foo instance;

void runThread()
{
instance.run();
}

但我仍然会研究是否可以让它与 std::atomic 一起挂起,因为如果这是原因,它仍然是一个与调用 std 的问题不同的问题: :thread::join()main 退出后。

关于c++ - 工作线程在 DLL(但不是 .exe)中的静态对象被破坏之前被强制终止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42535990/

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