C++ C++;通过引用将std::string传递给dll中的函数
我在通过引用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
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时,传统的版本和调试版本是不兼容的(这是因为在构建调试时需要额外的健全性检查,因此