【问题标题】:Can this C++ code for growing an array possibly break?这个用于增长数组的 C++ 代码可能会中断吗?
【发布时间】:2013-06-04 21:57:08
【问题描述】:

我最终决定永远学习C++,我在一本增加数组大小的书中遇到了下面的代码。该函数接受一个指向具有原始大小的数组的指针,并返回一个大小为两倍的新数组。

int *doubleArraySize(int *p_array, int *p_size) {
    *p_size *= 2;

    int *p_new_array = new int[*p_size];
    for(int i = 0; i < *p_size; i++)
        p_new_array[i] = p_array[i];

    delete[] p_array;
    return p_new_array;
}

当我们到达 for 循环时,*p_size 的值已经翻了一番。这意味着(至少对我而言)当我们访问p_array[i] 时,我们最终会进入不属于p_array 的内存区域。这是一个问题吗?这段代码会崩溃吗?如果没有,我错过了什么?

【问题讨论】:

  • 你在某个时候不需要malloc吗?
  • @njzk2 在 C++ 中?你什么时候也可以使用new
  • “这段代码会崩溃吗”?可能,也可能不是,或者可能只是在满月:) 关键是,这是未定义的行为,除非new 抛出并且你永远不会进入循环。
  • 您不应该为此使用标准库吗?你知道std::unique_ptrstd::vector 之类的东西吗?
  • 这段代码有很多麻烦:如果任何指针为空怎么办?如果p_array 不是用new[] 构造的呢?

标签: c++ arrays memory-leaks dynamic-memory-allocation


【解决方案1】:

new 可能会失败并引发异常。

还存在指针可能为 NULL 的风险。

【讨论】:

    【解决方案2】:

    您最大的问题是您将 *p_size 乘以 2 为时过早,因此您在 for 循环中读取了旧数组的末尾。

    您可以通过将乘法推迟到复制之后来解决此问题:

    int extend_arr(int *old, size_t *sz)
    {
        int *newarr = new int[*sz * 2];
        for (size_t i = 0; i < *sz; i++)
            newarr[i] = old[i];
    
        *sz *= 2;
        return newarr;
    }
    

    一个常见的警告:你为什么不改用std::vector有了vector,你可以只用resize()它,然后让标准库来做。

    【讨论】:

    • 也是因为提前调整,如果operator new抛出异常,*p_size的值就错了。
    【解决方案3】:

    这不是安全代码。您从p_array 复制超出其限制(如果它是以前的*p_size)。虽然它可能不会崩溃,但它仍然是未定义的行为

    我有两个建议:

    1. 使用std::vector!
    2. 如果不是,那么至少使用std::copy_n 进行复制(当然要使用正确的大小)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 2014-01-02
      • 2016-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多