[英]C++ Passing std::string by reference to function in dll
我有通過引用 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);
我嘗試通過調用函數逐步調試並查看函數內部的_sFileName
值。
_sFileName
在函數中設置任何值(例如, t4gs..\\n\\t
)。
我嘗試檢測任何堆損壞,但編譯器說沒有錯誤。
DLL 已在調試設置中編譯。 .exe 程序也在調試中編譯。
怎么了?? 幫助..!
PS 我用的是 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 編譯一個模塊,那么您必須為另一個模塊這樣做。 此外,您必須鏈接到動態運行時而不是靜態鏈接運行時。 后者會在每個模塊中產生不同的運行時實例。
看起來您正在導出成員函數。 這也需要一個通用的共享運行時。 並且您應該在整個類而不是單個成員上使用__declspec(dllexport)
。
如果您同時控制這兩個模塊,則很容易滿足這些要求。 如果您希望讓其他方生產一個或其他模塊,那么您就對這些其他方施加了重大限制。 如果這是一個問題,那么請考慮使用更便攜的互操作。 例如,代替std::string
使用const char*
。
現在,您可能已經在使用動態運行時的單個共享實例。 在這種情況下,錯誤將更加平淡。 也許調用約定不匹配。 鑒於您的問題中的細節很少,因此很難確定地說任何事情。
我遇到了類似的問題。 我解決了它同步配置屬性 - > C / C++設置。
如果你想要調試模式:
_DEBUG
定義。如果你想要發布模式:
_DEBUG
定義。 這兩個項目我的意思是 exe 和 dll 項目。
它對我有用,特別是如果我不想更改 dll 的任何設置而只想調整它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.