C++通过引用传递std :: string到dll中的函数

Ale*_*sey 6 c++ string dll pass-by-reference c++11

我有问题通过引用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"));
Run Code Online (Sandbox Code Playgroud)

这是函数头:

#define AFCLIBDLL_API __declspec(dllimport) 
AFCLIBDLL_API EAFCErrors CAFC::OpenArchive(std::string const &_sFileName);
Run Code Online (Sandbox Code Playgroud)

我尝试通过调用函数调试pass-by-step并查看_sFileName函数内部的值.

_sFileName在函数中设置任何值(例如,t4gs..\n\t).

我尝试检测任何堆损坏,但编译器说,没有错误.

DLL已在调试设置中编译..exe程序也在debug中编译.

怎么了??救命..!

PS我使用Visual Studio 2013.WinApp.

编辑

我已将func的标题更改为此代码:

AFCLIBDLL_API EAFCErrors CAFC::CreateArchive(char const *const _pArchiveName)
{
    std::string _sArchiveName(_pArchiveName);
    ...
Run Code Online (Sandbox Code Playgroud)

我真的不知道,如何修复这个bug ...

关于堆:它被分配在我们进程的虚拟内存中,对吧?在这种情况下,共享虚拟内存很常见.

Pau*_*zie 7

这个问题与STL没什么关系,而且与跨应用程序边界传递对象有关.

1)必须使用相同的项目设置编译DLL和EXE.您必须这样做,以便结构对齐和打包相同,成员和成员函数没有不同的行为,甚至更微妙,引用和引用参数的低级实现完全相同.

2)DLL和EXE必须使用相同的运行时堆.为此,您必须使用运行时库的DLL版本.

如果你创建了一个类似于std :: string的类(在内存管理方面),你会遇到同样的问题.

可能是内存损坏的原因是有问题的对象(std :: string)分配和管理动态分配的内存.如果应用程序使用一个堆,并且DLL使用另一个堆,那么如果你在DLL中实例化std :: string,那么它将如何工作,但是应用程序正在调整字符串的大小(意味着可能发生内存分配)?


Dav*_*nan 5

C++ 类std::string可以跨模块边界使用,但这样做会对模块产生很大的限制。简而言之,两个模块必须使用相同的运行时实例

因此,例如,如果您使用 VS2013 编译一个模块,那么您必须为另一个模块这样做。此外,您必须链接到动态运行时而不是静态链接运行时。后者会在每个模块中产生不同的运行时实例。

看起来您正在导出成员函数。这也需要一个通用的共享运行时。并且您应该__declspec(dllexport)在整个班级而不是单个成员上使用。

如果您同时控制这两个模块,则很容易满足这些要求。如果您希望让其他方生产一个或其他模块,那么您就对这些其他方施加了重大限制。如果这是一个问题,那么请考虑使用更便携的互操作。例如,而不是std::string使用const char*.


现在,您可能已经在使用动态运行时的单个共享实例。在这种情况下,错误将更加平淡。也许调用约定不匹配。鉴于您的问题中的细节很少,因此很难确定地说任何事情。