在C+之间传递结构中的字符串/数组+/C# 我把一个结构从C++传递给C++。< /P>

在C+之间传递结构中的字符串/数组+/C# 我把一个结构从C++传递给C++。< /P>,c#,c++,struct,interop,marshalling,C#,C++,Struct,Interop,Marshalling,C#代码: C++代码: struct Data { public: int number; int array[5]; char buffer[512]; //char *buffer; }; 上述方法效果良好。但是,如果我在C++中使用指针处理数据,我得到的错误如下: 未处理的异常:System.AccessViolationException:尝试读取或写入受保护的内存 为什么我不能在这里处理指针? 通过指针处理这种情况是否有利?第一个结构可以工作,因为它

C#代码:

C++代码:

struct Data
{
public:
    int number;
    int array[5];
    char buffer[512];
    //char *buffer;
};
上述方法效果良好。但是,如果我在
C++
中使用指针处理数据,我得到的错误如下:

未处理的异常:System.AccessViolationException:尝试读取或写入受保护的内存

为什么我不能在这里处理指针?
通过指针处理这种情况是否有利?

第一个结构可以工作,因为它在结构中分配数组。 第二个是有问题的,因为它只在结构中分配
int
指针和
char
指针(它是
sizeof(void*)
取决于您的平台),而不是
int
数组。
如果您坚持使用指针,您必须自己分配和释放内存(即
new
delete[]
)。

问题是如何在内存中表示数据

假设您有一个c#结构实例,它封送到非托管代码甚至文件

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct Data
{
[MarshalAs(UnmanagedType.U4)]
public int number = 5;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public int[] array = {0, 1, 2, 3, 4};

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]

public string buffer = "Happy new Year";
}
根据这一点,您的内存布局如下(在类似十六进制的视图中):

这里我们有前四个字节“050000”,它表示内存中“number”变量的数字“5”。(请注意,这些字节的顺序相反,因为英特尔体系结构是LittleEndian的,有关详细信息,请参阅)

对于名为“array”的数组,接下来的五个整数是“00”=0,“01 00”=1,“02 00”=2,“03 00”=3,“04 00”=4

字符串“buffer”表示如下:

"00 48" = H
"00 61" = a
"00 70" = p
"00 70" = p
"00 79" = y
"00 20" = <space>
"00 6E" = n
"00 65" = e
"00 77" = w
"00 20" = <space>
"00 59" = Y
"00 65" = e
"00 61" = a
"00 72" = r
sizeof(int)是4。所以变量“number”=“050000”的内存内容是第五个。阵列[0],阵列,阵列[2],阵列[3],阵列[4]布置在内存块“00”=0,“01 00”=1,“02 00”=2,“03 00”=3,“04 00”=4上。 其他所有内容都保留在缓冲区[512]变量中。但是在C++中,siZeof(char)=1。char数据类型通常用于用单字节编码表示旧的ASCII样式的文本。您应该改用wchar\t,它非常适合Unicode编码

现在让我们来看看

struct Data
{
public:
    int number;
    int *array;
    char *buffer;
};
此结构将投影到如上所述的相同内存布局上。 如果您在32位环境(win32)下运行 “数组”指针的内容将是“00”(指针为4字节) “缓冲区”指针将为“01 00”

如果您在64位环境(win64)下运行 “数组”指针的内容将是“00 00 01 00 00”(指针为8字节),缓冲区指针将是“02 00 00 03 00 00”


这些是一些无效的指针,谁知道它指向哪里。这就是为什么当你试图去引用它们时,你会受到访问违反。

你不能改变你的C++声明,也不改变C语言声明。在此之后,您将很快发现int[]不会飞行。带指针的结构是一个非常棘手的内存管理问题,谁负责再次释放内存从来都不是很清楚。您必须自己承担责任并使用IntPtr。并且担心C++代码是否会对数组和字符串进行深度复制,如果没有,那么下一个问题是保持这些指针有效。“每个Unicode字符都有两个字节表示”:这是不可能的;太多了。UTF-16以一个或两个16位代码单元对Unicode代码点进行编码。那么,我应该保留代码本身,还是修改它们以使用指针?哪个更安全?而且,转移到指针有什么好处吗?我会保持原样。那么,我应该让我的代码保持原样,还是修改它们以使用指针?哪个更安全?此外,转向指针有什么好处吗?
05 00 00 00 00 00 00 00
01 00 00 00 02 00 00 00
03 00 00 00 04 00 00 00
00 48 00 61 00 70 00 70 
00 79 00 20 00 6E 00 65 
00 77 00 20 00 59 00 65 
00 61 00 72
"00 48" = H
"00 61" = a
"00 70" = p
"00 70" = p
"00 79" = y
"00 20" = <space>
"00 6E" = n
"00 65" = e
"00 77" = w
"00 20" = <space>
"00 59" = Y
"00 65" = e
"00 61" = a
"00 72" = r
struct Data
{
public:
    int number;
    int array[5];
    char buffer[512];
    //char *buffer;
};
struct Data
{
public:
    int number;
    int *array;
    char *buffer;
};