为什么管理字符串做printf的工作? [英] Why does printf work with managed Strings?

查看:243
本文介绍了为什么管理字符串做printf的工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在通过挖掘一些非常旧的C ++ / CLI的code(旧语法.NET测试版),并都感到有点惊讶地看到这样的内容:

we are currently digging through some really old C++/CLI-Code (Old Syntax .NET Beta) and were a bit surprised to see something like this:

System::String ^source("Test-String");
printf("%s", source);

程序正确输出

The program correctly outputs

Test-String

我们想知道,为什么它可以通过托管字符串源的printf - 更重要的是:为什么它的工作原理的?我不希望它是一些方便,功能由编译器,因为下面不工作:

We are wondering, why is it possible to pass the managed string source to printf - and more importantly: Why does it work? I don't expect it to be some convenience-feature by the compiler because the following doesn't work:

System::String ^source("Test-String");
char pDest[256];
strcpy(pDest, source);

这产生了(不知何故预期)编译错误,指出系统::字符串^ 无法转换为为const char * 。所以,我唯一真正的解释是,通过一个管理引用的va_list超过了所有编译器检查和技巧本土code到使用指针到托管堆中。由于系统::字符串重新presented类似于字符 -array在内存中,的printf 可能工作。或者编译器转换为 pin_ptr 并传递,为的printf

This produces a (somehow expected) compiling error saying that System::String^ can't be converted to const char*. So my only real explaination is that passing a managed reference to a va_list surpasses all compiler-checks and tricks the native code into using a pointer into the managed heap. Since System::String is represented similar to a char-Array in memory, printf may work. Or the compiler converts to a pin_ptr and passes that to printf.

我不希望它自动元帅字符串^ 的char * ,因为这会导致没有任何参照实际的内存地址的坏内存泄漏。

I don't expect it to automatically marshal the String^ to char*, because that would result in a bad memory leak without any reference to the actual memory address.

我们知道,这不是一个很好的解决方案,并在后来的Visual Studio-版本中引入的各种编组方法提供了一种更好的方法,但是这将是非常有趣的,了解什么是真正发生在这里。

We know that this isn't a good solution and the various marshalling methods introduced by the later Visual Studio-Versions provide a way better approach but it would be very interesting to understand what is actually happening here.

谢谢!

推荐答案

我相信这是因为编译器把它变成这个IL:

I believe it is because the compiler is turning it into this IL:

call vararg int32 modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) printf(int8 modopt([mscorlib]System.Runtime.CompilerServices.IsSignUnspecifiedByte) modopt([mscorlib]System.Runtime.CompilerServices.IsConst)*, ..., string)

这最终为一个的PInvoke调用的printf ,所以运行时是有点偷偷摸摸的在整理给你。你仍然在管理运行时和运行时将提供marhsalling因为当它需要的服务。

Which ends up as a pinvoke call to printf, so the runtime is being a little sneaky by marshalling it for you. You are still in a managed runtime, and the runtime will provide marhsalling as a service when it's needed.

一些注意事项:

看来, CLR!GenericPInvokeCalliHelper 是这样做的提升在x86 .NE​​T 4工作站CLR。

It seems that clr!GenericPInvokeCalliHelper is doing this lifting on the x86 .NET 4 Workstation CLR.

以下不能正常工作

这是因为是直的C ++。它没有机会,因为它并不需要经过编组

That's because that is straight C++. It has no chance to go through marshalling because it isn't needed.

这篇关于为什么管理字符串做printf的工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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