我有问题,通过引用std :: string将函数传递给dll。
这是函数调用:
CAFC AFCArchive;
std::string sSSS = std::string("data\\gtasa.afc");
AFCER_PRINT_RET(AFCArchive.OpenArchive(sSSS.c_str()));
//AFCER_PRINT_RET(AFCArchive.OpenArchive(sSSS));
//AFCER_PRINT_RET(AFCArchive.OpenArchive("data\\gtasa.afc"));
这是函数头:
#define AFCLIBDLL_API __declspec(dllimport)
AFCLIBDLL_API EAFCErrors CAFC::OpenArchive(std::string const &_sFileName);
我尝试通过调用函数调试pass-by-step并查看函数内的_sFileName
值。
_sFileName
设置任何值(例如,t4gs..\n\t
)。
我尝试检测任何堆损坏,但编译器说,没有错误。
DLL已在调试设置中编译。 .exe programm也在debug中编译。
怎么了?帮助..!
P.S。我使用的是Visual Studio 2013. WinApp。
修改
我已将func的标题更改为此代码:
AFCLIBDLL_API EAFCErrors CAFC::CreateArchive(char const *const _pArchiveName)
{
std::string _sArchiveName(_pArchiveName);
...
我真的不知道,如何修复这个错误...
关于堆:它被分配在我们进程的虚拟内存中,对吧?在这种情况下,共享虚拟内存很常见。
答案 0 :(得分:7)
这个问题与STL没什么关系,而且与跨应用程序边界传递对象有关。
1)必须使用相同的项目设置编译DLL和EXE。你必须这样做,以便结构对齐和打包是相同的,成员和成员函数没有不同的行为,甚至更微妙,参考和参考参数的低级实现是完全相同的。
2)DLL和EXE必须使用相同的运行时堆。为此,您必须使用运行时库的DLL版本。
如果你创建了一个与std :: string类似的东西(在内存管理方面),你会遇到同样的问题。
内存损坏的原因可能是有问题的对象(std :: string)分配和管理动态分配的内存。如果应用程序使用一个堆,并且DLL使用另一个堆,那么如果你在DLL中实例化std :: string,那么它将如何工作,但是应用程序正在调整字符串的大小(意味着可能发生内存分配)?
答案 1 :(得分:4)
像std::string
这样的C ++类可以跨模块边界使用,但这样做会对模块产生很大的限制。简而言之,两个模块必须使用运行时的实例。
因此,例如,如果使用VS2013编译一个模块,则必须对另一个模块执行此操作。而且,您必须链接到动态运行时而不是静态链接运行时。后者导致每个模块中的运行时实例不同。
看起来您正在导出成员函数。这也需要一个共同的共享运行时。你应该在整个班级而不是个别成员上使用__declspec(dllexport)
。
如果您控制两个模块,那么很容易满足这些要求。如果您希望让其他方生成一个或另一个模块,那么您对其他方施加了重大限制。如果这是一个问题,那么考虑使用更便携的互操作。例如,代替std::string
使用const char*
。
现在,您可能已经在使用动态运行时的单个共享实例。在这种情况下,错误将更加平淡无奇。调用约定可能不匹配。鉴于您的问题中的细节级别很少,很难确定地说出任何内容。
答案 2 :(得分:0)
如果您想要调试模式:
_DEBUG
定义。如果您想要发布模式:
_DEBUG
定义。这两个项目我的意思是exe和dll项目 它对我有用,特别是如果我不想更改任何dll设置但只是调整它们。