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

C++ C++;通过引用将std::string传递给dll中的函数,c++,string,c++11,dll,pass-by-reference,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.OpenAr

我在通过引用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);
我尝试通过调用函数一步一步地调试,并查看函数中的
\u sFileName

\u函数中的sFileName
设置任何值(例如,
t4gs..\n\t

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

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

怎么了??救命啊

另外,我使用了Visual Studio 2013。WinApp

编辑

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

AFCLIBDLL_API EAFCErrors CAFC::CreateArchive(char const *const _pArchiveName)
{
    std::string _sArchiveName(_pArchiveName);
    ...
我真的不知道,如何修复这个错误


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

这个问题与STL无关,而与跨应用程序边界传递对象有关

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

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

如果您创建了一个类,该类的功能(在内存管理方面)与
std::string
类似,那么您也会遇到同样的问题


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

std::string
这样的C++类可以跨模块边界使用,但这样做会对模块造成重大限制。简单地说,两个模块必须使用相同的运行时实例

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

看起来您正在导出成员函数。这还需要一个公共的共享运行时。您应该对整个类而不是单个成员使用
\uu declspec(dllexport)

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



现在,您可能已经在使用动态运行时的单个共享实例。在这种情况下,错误将更加平淡无奇。也许调用约定不匹配。考虑到你问题中的细节不多,很难确定地说什么

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

如果需要调试模式:

  • 在两个项目的预处理器定义中设置
    \u DEBUG
    定义
  • 在两个项目的代码生成->运行时库中设置/MDd
如果您想要发布模式:

  • 删除两个项目中预处理器定义中的
    \u DEBUG
    定义
  • 在两个项目的代码生成->运行时库中设置/MD
两个项目我指的是exe和dll项目。

特别是当我不想更改dll的任何设置,而只想调整它们时,它对我很有用。

EXE和dll是否使用完全相同的编译器编译,使用完全相同的标志?否则,EXE和DLL之间的
std::string
和其他STL类型的定义可能不同,这可能会导致问题。我建议您保留DLL以使用定义良好的ABI。通过DLL接口传递分配的内存是自找麻烦。例如,DLL和调用应用程序可能不使用同一堆。@MattMcNabb,如果它们不使用同一堆,为什么会出现问题?它们仍然共享相同的地址空间,对吗?如果他添加到字符串中,它释放内存并分配新内存,另一个堆将无法释放,因为它不知道该块,等等。
basic\u string(const\u Elem*\u Ptr)
-它是在.c\u str()之后调用的<代码>\u Ptr
在输入函数时正确:“data\\gtasa.afc”因此,除了standart之外,我不使用任何其他内存分配管理器。DLL和EXE是用完全相同的设置编译的。它不仅仅是这样。您需要两个模块使用相同的运行时实例。相同的运行时实例。。。这是什么?是的。同一实例。@Aleksey-在项目设置中,必须将运行时设置为运行时的DLL版本。如果您不知道这一点,那么您需要知道,因为这对于代码的运行是绝对必要的。正是出于这个原因,COM定义了一组关于对象所有权的狭窄(相当不方便)类型和规则。OP可能会建议我们研究这些约定,因为它为这个问题提供了一个健壮的解决方案。还值得指出的是,在Windows上使用STL时,传统的版本和调试版本是不兼容的(这是因为在构建调试时需要额外的健全性检查,因此