繁体   English   中英

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

[英]Uninitialized memory in C++Builder / Delphi

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

  • 在堆栈上?
  • 在堆上?

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

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

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

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

由于caskey的回答仅涉及c ++我对delphi的回答:

在德尔福,请参阅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继承的?),请参阅http://docs.embarcadero.com/products/rad_studio/cbuilder6/EN/CB6_DevelopersGuide_EN。 PDF格式

我引用:

“因为数据成员可能在虚函数中使用,所以了解它们何时以及如何初始化是很重要的。在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样式类的数据成员。“

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

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

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

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

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

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

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

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

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

在Delphi上,据我所知:* vcl类自动初始化其字段。 *全球也是

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM