2

所以我可以手动解决这个问题,所以这不是一个紧迫的问题,但我认为这真的很奇怪:

在发生奇怪的事情之前,这是我的全部代码:

int main(int argc, char** arg) {

int memory[100];
int loadCounter = 0;
bool getInput = true;
print_memory(memory);

然后是其他一些不相关的东西。

打印内存只打印应该初始化为全零的数组,但前几个数字是:

+1606636544 +32767 +1606418432 +32767 +1856227894 +1212071026 +1790564758 +813168429 +0000 +0000

(加号和填充零仅用于格式化,因为一旦数组被填充,所有数字都应该是从 0-1000。列表的其余部分是零)

它也不是内存泄漏,因为我尝试初始化一个不同的数组变量,并且在第一次运行时它也给了我很多奇怪的数字。为什么会这样?

4

5 回答 5

2

既然您问“C++ 数组初始化到什么?”,答案是它们初始化到它们进入作用域时分配的内存中的任何内容。它们没有被初始化

请注意,某些编译器会在调试版本中将堆栈变量初始化为零;一旦您开始进行发布构建,这可能会导致讨厌的、随机发生的问题。

于 2013-09-29T00:46:09.953 回答
1

除了其他答案,请考虑以下问题:什么是数组?

在 Java 或 C# 等托管语言中,您使用高级抽象。C 和 C++ 不提供抽象(我的意思是硬件抽象,而不是像 OO 特性这样的语言抽象)。它们被设计为接近金属工作工作,即语言直接使用硬件(在这种情况下为内存)而没有抽象。

这意味着当你声明一个局部变量时,int a例如,编译器所做的就是说“好的,我要把内存块解释[A,A + sizeof(int)]为一个整数,我称之为'a' ”(其中 A 是开头之间的偏移量该块和函数堆栈帧的起始地址)。如您所见,编译器仅将内存段“分配”给变量。它不会做任何“魔术”,例如“创建”变量。你要明白你的代码是在一台机器上执行的,而这台机器只有一个内存和一个CPU。没有魔法。

那么函数执行开始时变量的值是多少呢?用变量的内存块所具有的数据表示的值。通常,从我们当前的角度来看,该数据没有意义(例如,可能是字符串以前使用的数据的一部分),因此当您访问该变量时,您会得到额外的值。这就是我们所说的“垃圾”:以前编写的数据在我们的上下文中没有意义。

这同样适用于数组:数组只是更大的内存块,有足够的空间容纳数组的所有值:[A,A + (length of the array)*sizeof(type of array elements)]。因此,在变量情况下,内存包含垃圾

通常,您希望在声明期间使用一组值初始化数组。您可以使用初始化列表来实现:

int array[] = {1,2,3,4};

在这种情况下,编译器将代码添加到函数中以使用该值初始化数组所在的内存块。

旁注:非 POD 类型和静态存储

以上解释的内容仅适用于POD 类型基本类型和基本类型数组等对于像类这样的非 POD 类型,编译器会添加对变量构造函数的调用,这些构造函数旨在初始化类实例的值(属性)。

此外,即使使用 POD 类型,如果变量具有静态存储规范,编译器也会使用默认值初始化其内存,因为静态变量是在程序启动时分配的。

于 2013-09-29T01:24:23.920 回答
1

您正在使用的数组是堆栈分配的:

整数内存[100];

当特定函数范围退出(在本例中为 main)或返回时,内存将被回收并且不会泄漏。这就是堆栈分配内存的工作方式。在这种情况下,您在堆栈上而不是在堆上分配了 100 个整数(在我的编译器上每个 32 位)。堆分配只是内存中的其他地方,希望远离堆栈。无论如何,堆分配的内存有泄漏的机会。在堆栈上分配的低级普通旧数据(就像您在代码中编写的那样)不会泄漏。

您在函数中获得随机值的原因可能是因为您没有初始化“内存”整数数组中的数据。在发布模式下,应用程序或 C 运行时(至少在 Windows 中)不会负责将该内存初始化为已知的基值。所以数组中的内存是上次堆栈使用该内存时留下的内存。它可能是几毫秒(最有可能)到几秒钟(不太可能)到几分钟(不太可能)。无论如何,它被认为是垃圾内存,必须不惜一切代价避免。

问题是我们不知道你的 print_memory 函数中有什么。但是,如果该函数不以任何方式改变内存,那就可以解释为什么你会得到看似随机的值。在使用它们之前,您需要先将这些值初始化为某个值。我喜欢像这样声明基于堆栈的缓冲区:

int 内存[100] = {0};

这是编译器用零填充整个数组的捷径。它也适用于字符串和任何其他基本数据类型:

字符我的姓名[100] = {0}; 浮动 NoMoney[100] = {0};

不确定你使用的是什么编译器,但如果你使用的是带有 Visual Studio 的微软编译器,你应该没问题。

于 2013-09-29T00:47:57.210 回答
0

main()运行之前,语言运行时设置环境。您必须通过在加载模块的入口点中断并观察堆栈指针来发现它在做什么,但无论如何,main不​​能保证您进入时的堆栈空间是干净的。

任何需要清理堆栈或malloc空间new的东西都可以自己清理。很多事情都没有。C[++] 不做不必要的事情。在 C++ 中,类对象可以具有隐式运行的非平凡构造函数,这些构造函数保证对象的设置以供使用,但数组和普通标量没有构造函数,如果你想要一个初始值,你必须声明一个初始值设定项。

于 2013-09-29T03:52:52.803 回答
0

堆栈上的局部变量未在 c/c++ 中初始化。c/c++ 的设计速度很快,因此它不会在函数调用时将堆栈归零。

于 2013-09-29T00:46:51.223 回答