c++二进制兼容dll POD类成员初始化导致崩溃

C++ binary compatible dll POD class member initialization causes crash

本文关键字:初始化 成员 崩溃 POD 二进制 dll c++      更新时间:2023-10-16

我试图在一个可以在Windows VS应用程序中使用的mingw构建的dll中创建一个编译器间兼容的类。我的问题是,当从VS程序调用函数时,我的类试图初始化成员变量时崩溃。使用STL或在相同的函数中创建局部变量都可以。

ConsoleApplication2.exe中0x6BEC19FE (test.dll)的未处理异常:0xC0000005:访问违反写入位置0x154EB01E.

简单的演示:

dll代码

#include <iostream>
class Tester 
{
public:
    virtual void test() = 0;
};
class TesterImp : public Tester
{
public:
    TesterImp(){}
    ~TesterImp(){}
    virtual void test() { 
        int test = 5; // fine
        m_test = 5; // access violation
    }
private:
    int m_test;
};
    extern "C"
    {
        __declspec (dllexport) Tester* Create()
        {
            return new TesterImp();
        }
    }

加载dll并调用test函数的主程序:

#include <iostream>
#include <Windows.h> 
class Tester 
{
public:
    virtual void test() = 0;
};
typedef Tester* (*createPtr)();
int main(int argc, const char **argv, char * const *envp) {
  HINSTANCE hGetProcIDDLL = LoadLibraryA("test.dll");
  if (hGetProcIDDLL == NULL) {
    std::cout << "could not load the dynamic library" << std::endl;
    return EXIT_FAILURE;
  }
  createPtr ctr = (createPtr)GetProcAddress(hGetProcIDDLL, "Create");
  if (!ctr) {
    std::cout << "could not locate the function" << std::endl;
    return EXIT_FAILURE;
  }
  std::cout << "dll loading success!" << std::endl;
  Tester* testf = ctr();
  std::cout << "Got test class" << std::endl;
  testf->test(); // crash if the member variable is referenced, fine otherwise with local variable initialization or STL use inside the function
  std::cout << "Running dll functions success!" << std::endl;
  return 0;
}

主程序是用VS2012在调试模式下编译的,dll是用g++从mingw -

g++ -shared -o test.dll test.cpp

有人能给我解释一下这种行为吗?

谢谢。

您可能使用的是旧版本的MinGW。直到4.7.0(我认为),MinGW在堆栈上传递this指针,这与MSVC在ecx中传递this指针的thiscall惯例不同。

从4.7.0开始,MinGW使用与MSVC相同的thiscall调用约定。

我还可以通过使用__attribute__((thiscall))属性在test.cpp中标记Tester::test()TesterImp::test()来成功地从MSVC中调用示例TesterImp::test()函数。这适用于MinGW 4.6.2,如果不使用该属性,将导致崩溃。