【问题标题】:C++ What exactly happened here? [closed]C++ 这里到底发生了什么? [关闭]
【发布时间】:2021-08-09 15:20:10
【问题描述】:

在编写程序时,我在动态数组中发现了一个意外行为。在我做了一些测试后,我最终得到了这段代码。

#include <iostream>

unsigned long index;

template<typename T>
class A
{
public:
    void Set()
    {
        T* target = new T[index];
        for (unsigned int i = 0; i < index; i++)
        {
            target[i] = i;
        }
        this->value_ = target;
        index++;
    }

    T* value_;
};

int main()
{
    A<int> test;
    test.Set();
    std::cout << test.value_[0] << '\n';
    test.Set();
    std::cout << test.value_[1];
}

返回以下值:

11104472
11075776

每次执行程序时值都会发生变化,但是,我认为输出将是“0”和“1”。我想它们是内存地址,但为什么程序返回它们而不是预期的输出?

【问题讨论】:

  • 问问自己:当我做T* target = new T[index];时,index的值是多少?我现在有多大的数组?
  • 你可能会这么想,但是一旦你进入了未定义的行为领域,就没有回头路了。就像加利福尼亚酒店那样;)
  • @Salty27:第二个也是一样。现在您正在分配一个大小为 1 的数组,并访问第二个元素。哎呀。
  • index 自动初始化为零:您都在访问数组末尾之外的一个元素。在第一个 Set 处,您创建了一个零元素数组,但随后您访问了第一个元素 ([0])。下一次,您创建一个包含一个元素的数组,然后访问第二个元素 ([1])。 (另外,你永远不会 delete[] 你创建的东西,每次调用 Set 时都会泄漏内存。)
  • @Salty27:或者将index的增量移动到Set()的顶部。

标签: c++ gcc


【解决方案1】:

看看index 会有哪些值。它用 0 初始化。所以在第一个 test.Set(); 中,您创建了一个长度为 0 的数组。甚至稍后再阅读它是错误的,并导致所谓的未定义行为。在 set 的第二次调用中,index 的值为 1,因此您创建了一个长度为 1 的数组,并将位置 0 上的第一个元素正确初始化为 0,但您随后尝试打印出 test.value_[1],这不是第一个元素,但第二个。记住数组索引从 0 开始。所以这也是越界读取,即错误的行为会受到随机行为的惩罚。

【讨论】:

    猜你喜欢
    • 2021-03-18
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    相关资源
    最近更新 更多