C#使用wchar_t *成员编组C ++结构有时会使堆损坏 [英] C# Marshalling a C++ struct with wchar_t* member occasionally leaves the heap corrupted
问题描述
我已声明struct
如下:
// C++
struct TestStruct
{
wchar_t* TestString;
};
以及相应的托管表示形式
and the corresponding managed representation
// C#
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TestStruct
{
[MarshalAs(UnmanagedType.LPWStr)]
public string TestString;
}
以及此功能:
// C++
__declspec(dllexport) void __stdcall FillMultipleStructs(TestStruct* testStructures, const short arrayLength)
{
for(int i = 0; i < arrayLength; i++)
{
const wchar_t stringToAllocate[] = L"foo";
const unsigned long size = wcslen(stringToAllocate) * sizeof(wchar_t) + sizeof(wchar_t);
wchar_t* allocatedString = static_cast<wchar_t*>(::CoTaskMemAlloc(size));
wcscpy_s(allocatedString, size, stringToAllocate);
(&testStructures[i])->testString = allocatedString;
}
}
由FillMultipleStructs
方法调用的
,它需要多个TestStructs
并在C ++代码中对其进行初始化.
which is called by the FillMultipleStructs
method, that takes multiple TestStructs
and initializes them in the C++ code.
// C#
[DllImport("the path", CallingConvention = CallingConvention.StdCall, EntryPoint = "FillMultipleStructs", ExactSpelling = true, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private static extern void _FillMultipleStructs([In, Out] TestStruct[] structures, [MarshalAs(UnmanagedType.I2)] short arrayLength);
public static IEnumerable<TestStruct> FillMultipleStructs(IEnumerable<TestStruct> structures)
{
TestStruct[] structuresArray = structures.ToArray();
_FillMultipleStructs(structuresArray, (short) structuresArray.Length);
return structuresArray;
}
调用代码的方式如下:
FillMultipleStructs(
new List<TestStruct>()
{
new TestStruct(),
new TestStruct(),
new TestStruct()
});
现在,问题是:有时,代码可以运行,但是,有时会出现a heap has been corrupted
错误.我不知道这是从哪里来的,也不知道为什么它偶尔会起作用,有时却不起作用.
Now, the question is: sometimes, the code works, however, sometimes I get an a heap has been corrupted
error. I do not understand where that comes from nor why it does work occasionally and sometimes it does not.
我想这与struct
的字符串成员的编组有关,因此,如果有人可以告诉我我的错误在哪里,或者有人可以将我指向正确的方向或向我展示正确的方法,做到这一点,我将非常高兴.
I guess it has to do with the marshalling of the struct
's string member, so, if anyone can tell me where my error is or if anyone can point me in the right direction or show me the proper way to do that, I would gladly appreciate that.
推荐答案
For anyone coming across this question struggling with the same problem, to summarize what pstrjds already said in a comment:
将其编组为
BSTR
,然后代替CoTaskMemAlloc
调用, 创建BSTR
对象
marshal as a
BSTR
and then instead of theCoTaskMemAlloc
call, createBSTR
objects
实际上意味着从
[MarshalAs(UnmanagedType.LPWStr)]
public string TestString;
到
[MarshalAs(UnmanagedType.BStr)]
public string TestString;
,而不是使用::CoTaskMemAlloc
在C++
中分配字符串,需要使用::SysAllocString
.
and instead of using ::CoTaskMemAlloc
to allocate a string in C++
, ::SysAllocString
needs to be used.
我不必更改C++
struct
的签名,因为BSTR
(在我的情况下)最终是wchar_t*
的typedef
.
I did not have to change the signature of the C++
struct
, since BSTR
(in my case) was in the end a typedef
for wchar_t*
.
这篇关于C#使用wchar_t *成员编组C ++结构有时会使堆损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!