在EXE / DLL

时间:2018-09-05 16:46:42

标签: c++ dll

我有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进行编译,并且无法更改它。

1 个答案:

答案 0 :(得分:0)

向量的内存在DLL中分配,并在exe中释放,因为向量可能在返回时(甚至只是RVO)使用了移动语义,该语义只是将指针移动到分配的内部。当您使用静态CRT时,这意味着将为内存分配一个crt,并为另一个实例释放内存,这会导致问题。

短篇小说-不要这样做。跨DLL边界公开C ++对象是不好的。您应该使用C接口或为此设计的接口-例如WinRT。

如果确实选择通过DLL接口公开c ++对象,则必须确保EXE和DLL使用相同版本的编译器,并与/ MD链接。如果您不能使用/ MD,则永远无法使它可靠地工作。

当然,您可以预先分配引导程序并将其填充在调用中,但这只是掩盖了问题,直到事情不可避免地改变了方向。