当试图从一个从DLL加载的类实例中访问基类向量时,程序崩溃。

时间:2022-03-12 06:50:56

I'm running into a strange crash. I am trying to separate out various modules of my Application (MFC based, developed in VS2005) into DLLs. Following is the skeletal code of how I'm trying to achieve it:

我遇到了一场奇怪的车祸。我正在尝试将我的应用程序的各个模块(基于VS2005开发的MFC)划分为dll。下面是我如何实现它的骨骼代码:

In a common Header file(say base.h):

在一个公共头文件(比如base.h):

class Base {
    vector<message> messages;
    ...
    ...
};

In a header file in DLL source code(say class.h):

在DLL源代码的头文件中(比如class.h):

class Derived : public Base {
private:
    int hoo();
    ...
public:
    void foo();
    int goo();
    ...
};

extern "C" __declspec (dllexport) Derived* CreateDerived();

In class.cpp

在class.cpp

 Derived* CreateDerived()
 {
    return new Derived;
 }

In a file in main Application code:

在主要应用程序代码中的一个文件中:

#include "base.h"
#include "class.h"

typedef Derived* (*DerivedCreator)();
...
...

void LoadDll()
{
    //DLL Load Code...
    ...
    ...

    DerivedCreator creator = reinterpret_cast<DerivedCreator>(::GetProcAddress(dllHandle, "CreateDerived"));

    Derived* pDerived = creator();

    pDerived->messages.push_back(message("xyz"));//Crashes here...
}

The problem is the code craches the moment I try to access the vector member of the Base class. This only happens in Release mode. It works fine in Debug mode. The error message that i get when I execute it from Visual Studio in Release mode is:

问题是,当我尝试访问基类的vector成员时,代码就会崩溃。这只在发布模式中发生。它在调试模式下运行良好。我在发布模式下从Visual Studio执行时得到的错误消息是:

"Microsoft Visual Studio C Runtime Library has detected a fatal error in Samsung SSD Magician.exe.

微软Visual Studio C运行时库发现了三星SSD Magician.exe的致命错误。

Press Break to debug the program or Continue to terminate the program."

按中断调试程序或继续终止程序。

But when I execute the release binary directly and attach the debugger to it, I get an Access Violation. At this point if I check the vector in debugger, it shows 6-digit entries in it, none of them readable. I'm able to see correct values of rest of the members of Base class in the Derived pointer.

但是当我直接执行释放二进制文件并将调试器附加到它时,我就会遇到访问冲突。现在,如果我在调试器中检查vector,它会显示6位的条目,没有一个是可读的。我可以在派生的指针中看到基类成员的正确值。

Any help would be much appreciated.

非常感谢您的帮助。

1 个解决方案

#1


2  

It's dangerous to pass stl containers across a DLL boundary. The reason here is that each module (the main application and the DLL) has it's own instance of the heap. If you allocate dynamic memory in the context of DLL, then pass the pointer to the application and release that memory in the context of the application, that causes heap corruption.

将stl容器传递到DLL边界是很危险的。这里的原因是每个模块(主应用程序和DLL)都有自己的堆实例。如果在DLL的上下文中分配动态内存,则将指针传递给应用程序,并在应用程序上下文中释放内存,从而导致堆损坏。

That is exactly what happens in your example.

这就是在你的例子中所发生的事情。

Derived* pDerived = creator();

CreateDerived is called.

CreateDerived。

 Derived* CreateDerived()
 {
    return new Derived;
 }

new Derived allocates memory in DLL heap.

new派生的分配内存在DLL堆中。

pDerived->messages.push_back(message("xyz"));

Inside push_back, an additional memory is allocated for Base::messages, and that allocation is done on the application heap. Crash!

在push_back中,为Base::消息分配一个额外的内存,并在应用程序堆上进行分配。崩溃!

A conclusion is that you need to rethink the DLL interface in order to perform all operation on the vector only inside the DLL.

结论是您需要重新考虑DLL接口,以便只在DLL内部执行所有的操作。

#1


2  

It's dangerous to pass stl containers across a DLL boundary. The reason here is that each module (the main application and the DLL) has it's own instance of the heap. If you allocate dynamic memory in the context of DLL, then pass the pointer to the application and release that memory in the context of the application, that causes heap corruption.

将stl容器传递到DLL边界是很危险的。这里的原因是每个模块(主应用程序和DLL)都有自己的堆实例。如果在DLL的上下文中分配动态内存,则将指针传递给应用程序,并在应用程序上下文中释放内存,从而导致堆损坏。

That is exactly what happens in your example.

这就是在你的例子中所发生的事情。

Derived* pDerived = creator();

CreateDerived is called.

CreateDerived。

 Derived* CreateDerived()
 {
    return new Derived;
 }

new Derived allocates memory in DLL heap.

new派生的分配内存在DLL堆中。

pDerived->messages.push_back(message("xyz"));

Inside push_back, an additional memory is allocated for Base::messages, and that allocation is done on the application heap. Crash!

在push_back中,为Base::消息分配一个额外的内存,并在应用程序堆上进行分配。崩溃!

A conclusion is that you need to rethink the DLL interface in order to perform all operation on the vector only inside the DLL.

结论是您需要重新考虑DLL接口,以便只在DLL内部执行所有的操作。