C ++ Builder / Delphi中未初始化的内存

时间:2009-06-06 14:05:04

标签: delphi c++builder initialization

Delphi中的未初始化变量是否保证具有任何特定值

  • 在堆栈上?
  • 在堆上?

由于C ++ Builder一般遵循Delphi的设计,C ++ Builder中的未初始化变量保证具有任何特定值

  • 在堆栈上?
  • 在堆上,对于从TObject派生的类的成员变量?
  • 在堆上,对于成员变量POCOs

我继承了一些C ++ Builder代码,这些代码很大程度上取决于成员变量的零初始化,并试图弄清楚语言是否能保证这一点。

当Windows首次提供给程序的堆栈或堆时,Windows是否保证内存为零初始化? (编辑:我意识到程序会在执行时覆盖内存,所以它不能继续依赖于此;我只是想弄清楚我观察到的行为。)

5 个答案:

答案 0 :(得分:7)

因为caskey的回答只涉及c ++我对delphi的回答:

在delphi中,请this answer

引用Giacomo Degli Esposti
  • 对象字段始终初始化为0,0.0,'',False,nil或其他任何适用的字段。
  • 始终初始化全局变量。 (到0)
  • 局部变量是单元化的,因此您必须先分配一个值才能使用它们。

MS-帮助://borland.bds4/bds4ref/html/Variables.htm

Giacomo Degli Esposti

的所有学分

编辑:“当Windows首次提供给程序的堆栈或堆时,Windows是否保证内存零初始化?

Windows保证在首次将内存初始化为新进程时对内存进行零初始化(否则,无论权限如何,程序都能够读取其他进程丢弃的内存时会遇到很大的安全问题)。但是使用c ++这个保证对你没有多大帮助,因为在你的代码有机会使用它之前,c-runtime可以自行覆盖内存。

Edit2 :对于c ++构建器变量显然是为“ VCL样式类”初始化的(无论这意味着什么,都是从TObject继承的?),请参阅{{3 }}

我引用:

“因为数据成员可能在虚拟功能中使用,所以重要的是 了解它们何时以及如何初始化。在Object Pascal中,所有未初始化的数据 是零初始化。例如,这适用于构造函数所在的基类 不用继承调用。 在标准C ++中,无法保证其价值 未初始化的数据成员。以下类型的类数据成员必须是 在类的构造函数的初始化列表中初始化: •参考文献 •没有默认构造函数的数据成员

尽管如此,这些数据成员的价值,还是那些在正文中初始化的成员 构造函数,在调用基类构造函数时是未定义的。 在C ++ Builder中, VCL样式类的内存为零初始化。

从技术上讲,它是VCL或CLX类的内存为零,即位是 零,这些值实际上是未定义的。例如,引用为零。

一个虚函数,它依赖于在中初始化的成员变量的值 构造函数的主体或初始化列表中的行为可能就像变量一样 初始化为零。这是因为基类构造函数在之前被调用 处理初始化列表或输入构造函数体。

#include <sysutils.hpp>
class Base : public TObject {
public:
    __fastcall Base() { init(); }
        virtual void __fastcall init() { }
    };
class Derived : public Base {
    public:
        Derived(int nz) : not_zero(nz) { }
        virtual void __fastcall init()
        {
        if (not_zero == 0)
        throw Exception("not_zero is zero!");
        }
    private:
        int not_zero;
};
int main(void)
{
    Derived *d42 = new Derived(42);
    return 0;
}

此示例在Base的构造函数中引发异常。因为Base是 在Derived之前构造的not_zero尚未使用值42初始化 传递给构造函数。请注意,您无法初始化您的数据成员 调用基类构造函数之前的VCL样式类。“

答案 1 :(得分:2)

简短回答:在C ++中你必须初始化所有内容

如果C ++ Builder与C ++类似,那么除非你明确地初始化它,否则不能保证内存的内容。

虽然Windows可能会在页面可用于程序的堆栈或堆之前留空,但除非您从操作系统请求自己的内存,否则您可能正在使用构造函数或库来进行内存分配。您经常会获得自己已经使用过的页面或内存区域。在这种情况下,它几乎可以保证是脏的。对于几乎从不是新页面的堆栈页面来说也是如此。

memset()将是您在C中擦除内存的方式,但在C ++中,您需要为每个字段提供默认值,或者在构造函数中显式初始化它们。

答案 2 :(得分:1)

在C ++中,保证在以下情况下初始化内存:

  • 用于静态分配的变量
  • 用于具有初始化其成员的构造函数的对象

在第一种情况下,POD数据类型(如整数,指针等)将初始化为零。

这些是C ++标准提供的唯一保证。 Windows在此区域根本不提供任何保证。

答案 3 :(得分:1)

在Delphi中,TObject构造函数初始化堆分配的(总是在堆上,因为TObject不能在Delphi中进行堆栈实例化)对象的内存,从而清除所有成员变量。

答案 4 :(得分:0)

在Delphi上,据我所知: * vcl类自动初始化其字段。 * Globals太

本地变量已初始化。他们的初始内容完全未定义。因此,如果变量是本地的,TObject类型的Assigned(变量)将一直返回 false