以下代码段的输出是什么?这是什么意思?

时间:2014-08-27 01:39:12

标签: c++

我正在攻读C ++ / OOP考试,并且在我的练习考试中对这个问题有点困惑。

以下代码段的输出是什么?

int *list = new int[5];
int *ptr;
for (int i = 0; i < 5; i ++)
list [ i] = i+ 1;
ptr = list;
delete [ ] list;
cout << *ptr
  1. 1
  2. 列表地址
  3. ptr的地址
  4. 错误 - ptr引用不再属于程序的内存
  5. 我找到了输出,即-17891602,但我是否正确,假设这只是对不再属于程序的内存的引用?因为我不一定会收到错误。

    自从我使用指针以来已经有一段时间了,所以我得到一个但是扭曲了试图遵循代码实际做的事情。 (我知道这与你们正在研究的一些东西相比很简单,但我只是开始学习这些东西:))

3 个答案:

答案 0 :(得分:3)

输出可以是任何内容(包括-17891602),因为您通过取消引用已取消分配其后备内存的指针来调用未定义的行为。

标准的相关部分是C++11 3.7.4.2 Deallocation functions /4(我的粗体):

  

如果给标准库中的释放函数赋予的参数是一个不是空指针值的指针,则释放函数将释放指针引用的存储,呈现无效指向任何部分的指针。解除分配的存储空间。使用无效指针值(包括将其传递给释放函数)的效果未定义。

在我的系统上,以下程序(以您的代码为模型):

#include <iostream>

int main (void) {
    int *list = new int[5];
    int *ptr;
    for (int i = 0; i < 5; i ++)
        list [ i] = i+ 1;
    ptr = list;
    delete [ ] list;
    std::cout << *ptr;
    return 0;
}

输出1,但绝不需要。

你的问题的正确答案很可能是4,虽然技术上并不是输出(你可能看不到&#34;错误&#34;字符串发送到输出然而,它是执行代码的结果

答案 1 :(得分:2)

我并没有在这方面发挥作用,但是HostileFork的答案(我+ 1ed)在错过了几个问题的时候深入研究 - 太容易评论,所以我在这里......

首先是问题:

  

以下代码段的输出是什么?

对于给出的代码,输出可能是 任何内容 ,这不是答案之一。不过,预期答案显然是4:

  

错误 - ptr引用不再属于程序的内存

那说:

  • 内存可能仍然属于程序/进程(大多数C ++实现不会释放内存,用于满足操作系统的小内存分配,直到程序终止),但它& #39; s不再拥有&#34;拥有&#34;通过您列出的应用程序级代码,delete[]将所有权返回到内存分配库

  • 问题不仅仅是ptr引用的内容,而且具体是ptr在指向已释放的内存时被取消引用

总的来说,问题措辞不多,但其背后的意图相当明确。

我不会重复解释未定义行为的解释,因为我不一定会收到错误。&#34;观察,因为HostileFork的答案很好。

尽管如此,即使编译器没有被C ++标准强制要求提供任何特定行为,计算机程序也不会擅自做任何奇怪的事情,在这种特殊情况下我在上面观察到的记忆可能仍然归程序所有,并且注意到执行*ptr之前delete[] list;的值必须是1,导致问题...

你为什么看到-17891602而不是1?

在预感中,我将其转换为无符号32位十六进制(如同):值{&#39;然后FEEEFEEE。维基百科说到"magic number"

  

由Microsoft调试HeapFree()用于标记释放的堆内存。

因此,Microsoft的delete[]函数触发了使用int覆盖五个0xFEEEFEEE位置,旨在让您 - 程序员 - 更容易看到您未定义行为。由于在程序运行时覆盖内存需要花费时间,并且仅在程序实际上已经破坏时才有用,无论如何,在制作和发布&#34;发布之前,您希望实现和修复该程序。这个FEEEFEEE - 填充行为只能在MS&#34; debug&#34;建立。其他编译器或malloc库通常提供类似的行为,由编译器标志/环境变量等启用。

答案 2 :(得分:1)

写这个问题的人要么不理解,要么写不好。可以通过在每一行插入一个单词来修复它:

  1. 绝对 1
  2. 绝对列表地址
  3. 绝对 ptr的地址
  4. 程序员错误 - ptr引用不再属于程序的内存
  5. 这个问题触及了一些名为&#34; Undefined Behavior&#34;的内容,你可以在这里阅读:

    https://softwareengineering.stackexchange.com/questions/99692/philosophy-behind-undefined-behavior

    这列出了一些原因 - 例如 - 编译器没有给你一个&#34;编译时错误&#34;或&#34;运行时异常&#34;。在一般情况下可能无法检测到先验,并且在运行时检查会增加不必要的开销,这是一个错误。