C#使用wchar_t *成员编组C ++结构有时会使堆损坏 [英] C# Marshalling a C++ struct with wchar_t* member occasionally leaves the heap corrupted

查看:252
本文介绍了C#使用wchar_t *成员编组C ++结构有时会使堆损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已声明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 the CoTaskMemAlloc call, create BSTR objects

实际上意味着从

[MarshalAs(UnmanagedType.LPWStr)]
public string TestString;

[MarshalAs(UnmanagedType.BStr)]
public string TestString;

,而不是使用::CoTaskMemAllocC++中分配字符串,需要使用::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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆