堆栈或堆上的这个对象?

时间:2016-08-20 10:41:07

标签: .net c++-cli heap-memory

在C ++ / CLI中,以下两个是相同还是不同?

System::String ^source("Hello World");

System::String ^source= gcnew System::String("Hello World");

第一个是堆栈,第二个堆栈吗? 或者他们都在堆上? .Net对象我认为只有引用它们不能在堆栈上创建,这与C ++允许我们不同。有人可以解释一下吗?

1 个答案:

答案 0 :(得分:7)

字符串既不存储在堆栈中,也不存储在堆中。这个故事有点令人费解。

考虑它的通常有用的方法是引用类型对象始终存储在GC堆上。非常类似于C ++(又名std :: string),像字符串这样的可变长度对象需要使用free store来分配正确的内存量。在std :: string中模拟可能的微优化,可以在std :: string对象中存储非常短的字符串。但通常std :: string对象本身可以在堆栈上分配,字符串 content 在堆上分配。就像source在堆栈上一样,只是一个垃圾收集器可以找回的普通指针。

C语言允许在堆栈上存储字符串内容,但您必须预先猜测所需的字符串缓冲区长度。发起成千上万的恶意软件攻击,字符串缓冲区溢出是一种标准技术,可以搞乱程序的堆栈帧并改变函数返回值。不是.NET方式。 C语言编译器没有这样做,它们只是非常普遍。

但在你给出的例子中,这不是直截了当的。语句之间没有区别,字符串内容既不在堆栈上也不在堆上分配。 CLR经过大量微优化,以利用CLI规范,该规范描述了字符串必须在符合CLR的实现中的行为。

它利用了字符串对象不可变的属性。这允许进行名为 interning 的优化。字符串对象的外观和行为与存储在GC堆上的行为相似。但事实并非如此,对象内容直接从程序集的内存映射图像中读取。存储在程序集元数据中的“blob堆”中。当GC收集时遇到这样的字符串对象时,GC会忽略它们。非常类似于字符串文字在C语言中的行为方式。减去发生十亿次崩溃的错误(字符串文字是char*而不是const char*,就像它应该的那样),由于不变性保证,你永远不会意外写入字符串文字。