Array of pointers in C++/CLI MSIL assembly

我只是一个虾纸丫 提交于 2019-12-05 03:43:44

This looks like an issue in the generated IL for the test method. At the point of the crash we're reading **c, and c is local number 5.

IL_00a5  11 05             ldloc.s      0x5
IL_00a7  4a                ldind.i4    
IL_00a8  4f                ldind.r8    
IL_00a9  28 11 00 00 0a    call         0xA000011

So here we see the IL says to load the value of c, then load a 4 byte signed integer, then treat that integer as a pointer and load an 8 byte real type (double).

On a 64 bit platform pointers should be either size-neutral or 64 bits. So the ldind.i4 is problematic as the underlying address is 8 bytes. And since the IL specifies reading only 4 bytes, the jit must extend the result to get an 8 byte value. Here it chooses to sign extend.

library.h @ 27:
00007ffd`b0cf2119 488b45a8        mov     rax,qword ptr [rbp-58h]
00007ffd`b0cf211d 8b00            mov     eax,dword ptr [rax]
00007ffd`b0cf211f 4863c0          movsxd  rax,eax   // **** sign extend ****
>>> 00007ffd`b0cf2122 c4e17b1000      vmovsd  xmm0,qword ptr [rax]
00007ffd`b0cf2127 e854f6ffff      call    System.Console.WriteLine(Double) (00007ffd`b0cf1780)

You apparently get lucky when running on full framework as the array address is small and fits in 31 bits or less, so reading 4 bytes and then sign-exending to 8 bytes still gives the right address. But on Core it doesn't and so that's why the app crashes there.

It appears you generated your library using the Win32 target. If you rebuild it with an x64 target the IL will use a 64 bit load for *c:

IL_00ab:  ldloc.s    V_5
IL_00ad:  ldind.i8
IL_00ae:  ldind.r8
IL_00af:  call       void [mscorlib]System.Console::WriteLine(float64)

and the app runs just fine.

It appears this is a feature in C++/CLI -- the binaries it produces are implicitly architecture dependent even in pure mode. Only /clr:safe can produce architecture-independent assemblies, and you can't use that with this code since it contains unverifiable constructs like pointers.

Also please note not all features of C++/CLI are supported in .Net Core 2.x. This particular example avoids unsupported bits, but more complex ones may not.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!