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

时间:2014-03-09 06:10:13

标签: c++ string c++11 dll pass-by-reference

我有问题,通过引用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);
    ...

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

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

3 个答案:

答案 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)

我遇到过类似的问题。 我解决了它同步配置属性 - > C / C ++ 设置。

如果您想要调试模式:

  • 在两个项目的预处理器定义中设置_DEBUG定义。
  • 代码生成中的设置/ MDd - >两个项目中的运行时库。

如果您想要发布模式:

  • 删除两个项目中预处理程序定义中的_DEBUG定义。
  • 代码生成中的设置/ MD - >两个项目中的运行时库。

这两个项目我的意思是exe和dll项目 它对我有用,特别是如果我不想更改任何dll设置但只是调整它们。