我已经搜索了很多,但似乎找不到与我所做的类似的解决方案。我有两个应用程序,一个是本地的C++应用程序,另一个是托管的C#应用程序。C++应用程序分配一组字节,用于内存管理器。在此内存管理器中分配的每个对象都具有标题,每个标题都有一个指向对象名称的char*。C#应用程序充当此内存的查看器。我使用内存映射文件使C#应用程序能够在C++应用程序运行时读取内存。我的问题是,我正在尝试从标题结构中读取对象的名称并在C#中显示它(或者只是将其存储在字符串中)。使用unsafe代码,我能够将组成char*的四个字节转换为IntPtr,将其转换为void*,并调用Marshal.PtrToStringAnsi。这是代码:
在这种情况下,
我已经验证,在托管方面,调用
这段代码产生不同的结果。有时
在C++方面,我想可能存在一些问题,实际上无法读取存储指针的内存,因为存储文本的实际字节不是内存映射文件的一部分。因此,我查看了如何更改对内存的读/写访问权限(在Windows上),并找到了Windows库中的VirtualProtect方法,我使用它来将内存的访问权限更改为PAGE_EXECUTE_WRITECOPY,我认为任何具有该地址指针的应用程序都能够至少读取其中内容。但这也没有解决问题。
简而言之:
我在C#中有一个指向char数组中第一个char的指针(该数组是在C++应用程序中分配的),并正在尝试将那些char数组读入C#中的字符串中。
编辑:
源标题看起来像这样:
IntPtr namePtr = new IntrPtr(BitConverter.ToInt32(bytes, index));
unsafe
{
void* ptr = namePtr.ToPointer();
char* cptr = (char*)ptr;
output = Marshal.PtrToStringAnsi((IntPtr)ptr);
}
在这种情况下,
bytes
是从内存映射文件中读取的数组,表示本机应用程序创建的所有字节池,而index
是名称指针的第一个字节的索引。我已经验证,在托管方面,调用
namePtr.ToPointer()
返回的地址正好是本机应用程序中名称指针的地址。如果这是本机代码,我只需将ptr
转换为char*
即可,但在托管代码中,我必须使用Marshaller来完成这个过程。这段代码产生不同的结果。有时
cptr
为空,有时指向\0
,有时指向几个亚洲字符(当通过PtrToStringAnsi
方法运行时,会产生看似不相关的字符)。我认为这可能是一个fixed
问题,但ToPointer
会产生一个固定的指针。有时,在将其转换为char*
之后,调试器会说无法评估表达式。指针无效
或类似的内容(不容易复制每个变化的事物)。其他时候,当读取内存时,我会收到访问冲突的消息,这导致我进入了C++的一面。在C++方面,我想可能存在一些问题,实际上无法读取存储指针的内存,因为存储文本的实际字节不是内存映射文件的一部分。因此,我查看了如何更改对内存的读/写访问权限(在Windows上),并找到了Windows库中的VirtualProtect方法,我使用它来将内存的访问权限更改为PAGE_EXECUTE_WRITECOPY,我认为任何具有该地址指针的应用程序都能够至少读取其中内容。但这也没有解决问题。
简而言之:
我在C#中有一个指向char数组中第一个char的指针(该数组是在C++应用程序中分配的),并正在尝试将那些char数组读入C#中的字符串中。
编辑:
源标题看起来像这样:
struct AllocatorHeader
{
// These bytes are reserved, and their purposes may change.
char _reserved[4];
// A pointer to a destructor mapping that is associated with this object.
DestructorMappingBase* _destructor;
// The size of the object this header is for.
unsigned int _size;
char* _name;
};
_name
字段是我在C#中尝试解引用的字段。
编辑:
截至目前,即使使用下面提供的解决方案,我仍然无法在托管代码中解引用这个char*。因此,我只是在内存映射文件引用的池中制作了char*的副本,并使用指针指向它。这有效,这让我相信这是一个与保护相关的问题。如果我找到了绕过这个问题的方法,我会回答自己的问题。在那之前,这将是我的解决方法。感谢所有帮助我的人!
GetBytes()
,您将不得不在数组上使用fixed
块,以将其转换为指针。 - Richard J. Ross IIInew string(addr, 0, len)
。 - Marc Gravell