我有一个似乎是由我的编译器引起的问题。当我使用Mingw编译DLL时,一切似乎都正常。当我用MSVC编译DLL时,代码似乎阻塞在createMdl
中的某个地方。该过程保持0%的CPU使用率,我从不从下面的函数createMdl
函数调用返回。
此代码在一个大型远程环境中运行,因此要在我的机器上进行调试,我创建了一个描述下面问题的框架。不幸的是,这段代码并没有表现出我所看到的行为,但确实描述了我试图做的事情。
申请:
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <windows.h>
int main()
{
boost::asio::io_service io;
boost::asio::io_service::work work(io);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
HMODULE h = LoadLibrary("MyLib.dll");
typedef void (*createMdl_fn)(void*);
createMdl_fn createMdl = (createMdl_fn)GetProcAddress(h, "createMdl");
createMdl((void*)&io);
}
DLL:
#include <boost/asio.hpp>
extern "C" __declspec(dllexport) void __cdecl createMdl(void* io)
{
boost::asio::io_service* io_svc = (boost::asio::io_service*)io;
boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::udp::v4(), 12345);
boost::asio::ip::udp::socket sock(*io_svc, endpoint);
char* buf = new char[256];
sock.async_receive_from( boost::asio::buffer(buf, 256),
endpoint,
[buf](const boost::system::error_code& e,
std::size_t b){});
}
你能看到这种方法的缺陷吗?这种方法有什么不稳定的吗?如果您认为(void*)
的{{1}}投射是个问题,那么在使用io_service
时如何进行?请注意,无论使用哪种编译器编译应用程序,我都会遇到相同的行为。
我可以看到的一个大问题是,如果我使用新版本的boost重新编译库,GetProcAddress
的定义可能会发生变化,这可能会导致问题,但这并不能解释问题我和#39;我现在有。
答案 0 :(得分:1)
如果你在不同的编译单元/ DLL /可执行文件/之间传递C ++对象,你必须使用相同的编译器构建它们,否则绝对保证一切都会爆炸并爆炸。
不同的C ++编译器具有非常不兼容的ABI。这与C编译器形成鲜明对比,通常在任何给定平台上具有兼容的ABI,并且可以安全地混合和匹配。
无需将指针转换为void *或将函数声明为extern&#34; C&#34;在这种情况下。 (除了使用GetProcAddress的函数外)。
只有在您将它们之间共享的数据限制为内置类型和C兼容结构时,才能使用不同的C ++编译器。永远不要使用虚函数或访问说明符,指向成员或标准库类型的类 - 简而言之,没有什么能使C ++与C不同。如果使用不同的C ++编译器,则必须声明函数和对象在整个边界为extern "C"
。
使用来自一个供应商的C ++编译器和来自不同供应商的C编译器通常不是问题。