3

我有一个使用非托管 C++ 静态库的 C# 项目。当 C# 从非托管代码中取回字符串时,我遇到了一个奇怪的错误。程序崩溃,VS 告诉我可能的堆损坏。该字符串是非托管代码中对象中的一个字段 - 所以它不是局部变量问题。奇怪的是,崩溃总是在调试模式下发生,但仅在实际运行程序时的某些非常特殊的情况下才会发生。此外,尽管调试崩溃可以在所有计算机上重现,但运行时崩溃仅发生在某些计算机上。

我应该注意,我有许多从非托管代码导出的函数,除了这个函数和另一个做几乎相同事情的函数(GetBlockInfo)之外,它们都不会引起问题。

这是导致崩溃的代码行:

string info = CppToCsharpAdapter.GetFileInfo(myHashFilePointer);

CppToCsharpAdapter 是我的托管/非托管代码适配器。CppToCsharpAdapter.GetFileInfo 调用在我的非托管代码中执行对 GetFileInfo 函数的调用。

这是.cpp中的导出函数:

__declspec(dllexport)   const   char* __stdcall  GetFileInfo(HashFile* THIS)
{
      return THIS->GetFileInfo().c_str();   
}

这是非托管代码中的 GetFileInfo 函数:

string& GetFileInfo()
{
    try
    {
        LogicalHeaderBlock *infoBlock = LogicalFHBuffer;
        stringstream infoString;
        infoString<<infoBlock->getHashFuncID()<<endl;

             // many more lines//

        fileInfo = infoString.str();
        return fileInfo;

    }
    catch(exception &e)
    { throw e; }
}

这是导致崩溃的调用堆栈:

ntdll.dll!770a04e4()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
ntdll.dll!77062a2a()    
ntdll.dll!770a1b71()    
oleaut32.dll!75c43e59()     
[Managed to Native Transition]  
mscorlib.dll!System.StubHelpers.AnsiBSTRMarshaler.ClearNative(System.IntPtr pNative) + 0x45 bytes   
FMS_adapter.dll!FMS_adapter.HashFile.GetFileInfo() Line 249 + 0xb bytes C#

编辑:更新了调用堆栈,现在我得到了[Managed to Native Transition]清楚地表明问题存在的行。

任何帮助将不胜感激。提前致谢。

编辑:我最终通过让 C# CppToCsharpAdapter.GetFileInfo() 函数返回一个 IntPtr,然后将其转换为 C# 中的字符串来解决问题。

4

2 回答 2

2

问题出在您的 P/Invoke 定义中CppToCsharpAdapter.GetFileInfo,您的问题中没有包含该定义。至少,它需要添加以下属性:

[return: MarshalAs(UnmanagedType.LPStr)]

如果省略此属性,P/Invoke 层将假定返回的字符串在代码中由 a 表示BSTR,但您实际上使用的是以空值结尾的 ANSI 字符串。此链接有更多信息:

字符串的默认封送处理:平台调用中使用的字符串

于 2013-06-18T13:42:16.997 回答
0

您的 DLL 导出GetFileInfo()函数返回一个raw const char*,但我不确定这是托管代码的正确类型(除非您使用正确的 P/Invoke 签名......)。

您是否考虑过BSTR退货?BSTR是一个典型的COM 字符串,我认为 .NET 对 COM 的理解非常好,因此它也可以自动释放本机代码返回的 COM 分配的字符串。

__declspec(dllexport) BSTR __stdcall GetFileInfo(....)
{
    ....

    // Assume that "nativeString" is "const char*".

    // We first convert from ANSI/MBCS to Unicode:
    // (CA2W is a conversion helper defined in <atlconv.h>)
    CA2W unicodeNativeString( nativeString );

    // ...and then we return a BSTR built from it:
    return ::SysAllocString( unicodeNativeString );
}

编辑:

附带说明一下,另一个(不是 DLL 导出的)GetFileInfo()函数返回 a string&,但我建议您只string 按值返回 a (即只返回string而不是 string&)。

于 2013-06-18T10:10:47.180 回答