我有DLL和EXE应用程序。 DLL在EXE中注册。然后在EXE类A
中的实例创建为shared_ptr
。接下来,将此实例传递给DLL,并在DLL端调用此实例的方法example
。
class Result
{
//Some attributes e.g std::vector
}
class A
{
public:
A(){}
~A(){}
Result example(){
Result r;
//Fill data in r object....
return r;
}
}
问题是在DLL中某个地方调用example
时:
void someDLLMethod()
{
//a is a shared pointer of A class
{
Result r = a->example();
}//PROBLEM IS HERE DURING DEALLOCATING Result OBJECT
//some stuff...
}
似乎在删除r
对象期间发生了问题。我知道何时我将尝试在EXE中分配一些内存,然后尝试在DLL中分配该内存,然后会出现内存问题,但是在这种情况下,Result
对象从EXE复制到了DLL。另外,存储在Result
对象中的vector不包含任何指针,因此它应该是vector的深层副本。
一种解决方案是在DLL中分配Result
对象,将其作为对被调用方法的引用传递,并填充所有必要的数据,但是我想获取副本作为结果。
为什么会出现此问题?如何解决? EXE和DLL在Visual Studio的同一解决方案中,必须使用\ MT或\ MTd进行编译,并且无法更改它。
答案 0 :(得分:0)
向量的内存在DLL中分配,并在exe中释放,因为向量可能在返回时(甚至只是RVO)使用了移动语义,该语义只是将指针移动到分配的内部。当您使用静态CRT时,这意味着将为内存分配一个crt,并为另一个实例释放内存,这会导致问题。
短篇小说-不要这样做。跨DLL边界公开C ++对象是不好的。您应该使用C接口或为此设计的接口-例如WinRT。
如果确实选择通过DLL接口公开c ++对象,则必须确保EXE和DLL使用相同版本的编译器,并与/ MD链接。如果您不能使用/ MD,则永远无法使它可靠地工作。
当然,您可以预先分配引导程序并将其填充在调用中,但这只是掩盖了问题,直到事情不可避免地改变了方向。