代码之家  ›  专栏  ›  技术社区  ›  Josh Kelley

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

  •  2
  • Josh Kelley  · 技术社区  · 15 年前

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

    • 在堆栈上?
    • 在堆上?

    由于C++Builder通常遵循Delphi的设计,C++生成器中的未初始化变量保证有任何特定值。

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

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

    当内存第一次被分配给程序的堆栈或堆时,Windows是否保证内存初始化为零?( 编辑: 我意识到程序在执行时会覆盖内存,因此它不能继续依赖于此;我只是想找出我观察到的行为。)

    5 回复  |  直到 15 年前
        1
  •  7
  •   Community Egal    7 年前

    因为凯斯凯的答案只涉及C++对德尔菲的回答:

    在Delphi中,请参阅 this answer 通过 Giacomo Degli Esposti

    • 对象字段始终初始化为0、0.0、“”、false、nil或任何适用项。
    • 全局变量总是初始化的。(0)
    • 局部变量是统一的,因此在使用它们之前必须赋值。

    MS-HELP://borland.bds4/bds4ref/html/variables.htm(MS-HELP://borland.bds4/bds4ref/html/variables.htm)

    所有学分 艾斯波斯蒂

    编辑 : 当内存第一次被分配给程序的堆栈或堆时,Windows是否保证内存初始化为零?

    Windows保证当内存第一次被分配给一个新进程时,它是零初始化的(否则,无论权限如何,程序都能读取其他进程丢弃的内存,这会带来很大的安全问题)。然而,使用C++,这种保证对你没有多大帮助,因为C代码运行时可以在代码有机会使用之前自行重写内存。

    编辑2 对于C++ Builder变量,显然是为“ VCL样式类 “(不管这意味着什么,所有从托布特继承的东西?)见 http://docs.embarcadero.com/products/rad_studio/cbuilder6/EN/CB6_DevelopersGuide_EN.pdf

    我引述:

    “由于数据成员可用于虚拟函数,因此必须 了解何时以及如何初始化它们。在对象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的构造函数中引发异常。因为底部是 在派生之前构造,而不是用值42初始化 传递给构造函数。请注意,您不能初始化 调用其基类构造函数之前的VCL样式类。“

        2
  •  2
  •   caskey    15 年前

    简短的回答:在C++中,你必须初始化所有的东西。

    如果C++Builder是C++之类的东西,那么除非明确地初始化它,否则不存在对内存内容的保证。

    虽然Windows可能会在程序堆栈或堆可用之前清空页面,但除非您从操作系统请求自己的内存,否则您可能会使用构造函数或库来分配内存。更多的时候,你会得到一个你已经使用过的页面或记忆区域。在这种情况下,它肯定是脏的。对于几乎不属于新页面的堆栈页面,这是双倍的。

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

        3
  •  1
  •   anon    15 年前

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

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

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

    这些是C++标准给出的唯一保证。在这方面,窗户一点也不保证。

        4
  •  1
  •   Ville Krumlinde    15 年前

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

        5
  •  0
  •   Fabricio Araujo    15 年前

    关于德尔福,据我所知: *VCL类自动初始化其字段。 *全球

    局部变量是 初始化。它们的初始内容完全没有定义。因此,被分配的(变量)tobject类型将返回 任何时候如果 变量 是本地的。