Sec*_*ret 5 c# pointers memory-management unsafe marshalling
在这里,我正在尝试使用C#的不安全功能:http://ideone.com/L9uwZ5
我知道,在C#中这样的方式是最糟糕的,我想承认,主题中有一些信息.看看"变态"这个词.
我想在C#中实现快速排序,如pure-C方式(甚至不是C++).它可能很疯狂,但只是想深入了解不安全的C#的可能性.
我一直在尝试使用stackalloc运算符.我知道,这是来自堆栈的分配,而不是来自堆的分配,这就是我执行程序失败的原因.
但是当我在这个程序中没有看到任何异常/错误时我很困惑.
另外,正如您所看到的代码的注释部分:
struct Header
{
internal int* data;
};
Header* object_header = stackalloc Header[sizeof(Header)];
object_header->data = stackalloc int[length];
Run Code Online (Sandbox Code Playgroud)
我无法用最后一行编译它.C#编译器告诉我,在这个表达式中无法使用stackalloc.为什么?data是int*类型,为什么会出现错误?
我只想使用堆栈框架而不是使用堆.我知道,还有另一种方法,但它是来自堆的分配.
int*[] data = new int*[length * sizeof(int)];
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(length * sizeof(int)));
Marshal.WriteInt32(result, 0);
for(int i = 0; i < length * sizeof(int); i++) d[i] = (int*)result;
Run Code Online (Sandbox Code Playgroud)
例如,但它不是堆栈分配.
我怎么能用C#语言中的stack-allocation和pure-C style语法显式地解决我的perversion任务.
C#不是为这样的目标而创建的,而且这些功能很愚蠢 - 我知道,但主要的问题不是重要性,而是关于这些功能.
Marc展示了解决方法,我将尝试解释为什么这是必需的.实际上,您正在编写非托管代码,但该方法仍然是一种托管方法.它从IL编译成机器代码,垃圾收集器将搜索其堆栈帧和cpu寄存器以进行对象引用.
抖动在编译方法时执行两个重要的任务.一个是显而易见的,高度可见,将IL转换为机器代码.但是还有另一项非常重要的任务,它完全不可见,它为方法生成元数据.一个表,显示堆栈框架的哪些部分包含对象引用以及哪些部分存储指针和值类型值.在代码中的哪个点,cpu寄存器将存储对象引用.此外,在方法代码中的什么位置,对象引用超出范围.GC.KeepAlive()的原因,一个非常独特的方法,根本不生成任何代码.
垃圾收集器需要该表来可靠地查找对象引用.然而,该表只有一个间接层.它可以描述为分配OBJECT_HEADER栈空间并标记指针和指向的堆栈区为"不扫描对象引用".当您直接分配object_header-> data时,它无法描述堆栈空间的块.它没有额外的间接来将堆栈细分为更小的部分并描述Header.使用虚拟局部变量可以解决问题.