.net core 2.2+版本,在测试时候发现的奇妙问题。测试时是在 5.0 上发现的,但是似乎所有版本.net core 都存在这个特性。
Marshal.AllocHGlobal 时, 对于 UnmanagedType.LPUTF8Str,Alloc 的是指针的指针,PtrToStructure 读取的也是指针的指针 对于 UnmanagedType.ByValTStr,Alloc 的是指针,PtrToStructure 读取的也是指针
上下 2 组,上面是 LPUTF8Str 的测试结果,下面是 ByValTStr 的。 每一组第一行是 Marshal.AllocHGlobal 的返回值,第二行是 Marshal.ReadIntPtr(前面的返回值)的值
两部分只有 MarshalAs(UnmanagedType...)的定义不同,其他部分完全一样。 究竟这里是怎么回事…
完整的测试代码在这里 https://pastebin.com/J5cUmyfm
此外,这个特性似乎还跟.net core 版本有关…2.1 之前的版本在 Console.WriteLine(utf8Struct.Value)时候甚至会乱码,像这样: 3.0 之后直到 5.0 则都可以正常显示。这又是个什么奇怪的问题…
多谢各位大佬的赐教!
1
geelaw 2020-12-06 07:27:46 +08:00 via iPhone 1
如果是 LPUTF8Str,对应的非托管字段是 byte *,如果是 ByValTStr 、结构是 Unicode 、设置的 SizeConst 为 30,则对应的非托管字段是 30 个 ushort 。两个结构的非托管形式完全不同。
AllocHGlobal 出来的是一段定长内存的指针,至于怎么解读是代码的事儿。 早期 .NET 在取消封送 LPUTF8Str 时有 bug,见 https://github.com/dotnet/runtime/issues/11968 最后你的代码有内存泄露,在 FreeHGlobal 之前你应该 DestroyStructure,否则运行时不可能知道封送入 structPtr 而产生的 UTF-8 字符串需要释放。 |