【问题标题】:C++ dynamic array, increasing capacityC++动态数组,增加容量
【发布时间】:2014-06-19 15:26:40
【问题描述】:

我正在尝试实现一个动态数组,这是我增加容量的函数

int* changeCapacity(int *arr, int length, int newCapacity) {
    int *newArr = new int[newCapacity];

    if(length > newCapacity){
        return 0;
    } else {
        for(int i = 0; i < length; i++){
            newArr[i] = arr[i];
        }
        delete[] arr;
        arr = newArr;
        return arr;
    }
}

这是我得到的错误:

speicher(2465,0x7fff7cfc2310) malloc: * 对象 0x7f9742403910 的错误:未分配被释放的指针 * 在 malloc_error_break 中设置断点进行调试

我这样称呼它:

int* addElement(int *arr, int& length, int& capacity, int val){
if(length >= capacity){
    capacity = capacity * 2;
    changeCapacity(arr, length, capacity);

    arr[length] = val;
    length += 1;
    return arr;
}else{

    arr[length] = val;
    length += 1;
    return arr;
}

}

【问题讨论】:

  • 如果length &gt; newCapacity,你正在泄漏内存。
  • 您正在使用 C++。使用std::vector&lt;int&gt; 会处理所有这些问题。然后你就可以早点回家了。
  • 你能告诉我们你是如何调用这个函数的吗?
  • 你为什么认为他是他?
  • arr[length] 超出length 对象数组的范围,但我认为这不是问题所在。这两个函数都没有调用free(),所以我认为问题可能出在其他地方......另外,在changeCapacity() 中,我认为对于新请求的容量小于现有容量的情况返回 0 可能不是明智的设计选择...

标签: c++ arrays dynamic capacity


【解决方案1】:

我认为您的问题必须来自两件事 IMO

第一

changeCapacity(arr, length, capacity);
arr[length] = val;

这里没有新的 arr 值(由 changeCapacity() 返回)。 因此,您的函数 addElement() 将返回错误的指针,并在您的下一个 addElement() 上执行释放内存损坏。

为什么要获取新的 arr 值?

你做的和这里一样

a = 1;
changeVar(a);
// value of a here?

int changeVar(int a)
{
   a = 5;
   return (a);
}

a 的价值如何? 1 因为changeVar的参数是一个局部变量。

第二:

您在 addElement() 函数上赋予 NULL 值。

【讨论】:

    【解决方案2】:

    现在您正在更改arr 的地址,您必须在其中通过引用传递指针。这样做:

    int* changeCapacity(int *&arr, int length, int newCapacity)
    

    【讨论】:

    • 如果 OP 使用返回值,则不需要,因为新指针是从 changeCapacity 返回的。
    • 这就是为什么完整的代码示例很重要。真正的问题可能是他如何使用函数,而不是函数本身。
    • 当容量不需要增加时,OP 还必须修复返回 0。这是一个糟糕的选择。
    • 或者使用自己的返回值
    • 如果在参数中给出引用,为什么要返回 int*?
    【解决方案3】:

    这在某种程度上是基于错误消息的猜测,但您已经表明:

    int* addElement(int *arr, int& length, int& capacity, int val)
    { //...
      changeCapacity(arr, length, capacity);
      //...
    }
    

    调用:

    int* changeCapacity(int *arr, int length, int newCapacity)
    { //...
      delete[] arr;
      //...
    }
    

    但是,鉴于您迄今为止发布的代码,addElement()arr 参数的原始来源未知。你是不是碰巧做了这样的事情:

    foo()
    { int array[N];
      //...
      addElement(array, ...);
      //...
    }
    

    或者使用全局数组变量调用addElement()?在任何一种情况下,原始数组都不是通过new[] 分配以匹配delete[],这似乎是运行时库所抱怨的。错误信息中指出的指针的值往往让我认为它最初是在堆栈上分配的。

    当然,其他问题,例如没有捕获changeCapacity() 和/或addElement() 的返回值,以及changeCapacity() 可能返回空指针的可能性仍然有效,应该修复。

    【讨论】:

      【解决方案4】:

      这是一种更好的方法。所有想学习的人都在 cmets 中得到了很好的解释:

              #include <iostream>
              using namespace std;
      
              int* changeCapacity(int *arr, int length, int newCapacity);
              int* addElement(int *arr, int& length, int& capacity, int val);
      
              int main(){
                  int length = 0; // no inital elements in array
                  int capacity = 1; // initial capacity is one
                  int* arr = new int[capacity]; // allocating space for values
                  int* temp; // pointer for storing temporary values
                  /* loop for adding elements to the array */
                  for(int i=0;i<21;i++){
                      temp = addElement(arr,length,capacity,i); // adding an element to the array
                      if(temp == NULL) { // checks if execution was successful
                          cout<< "NULL returned...\n Exiting Now...";
                          return 0; // exits the program on failure
                      }
                      arr = temp; // changing the value of arr
                  }
                  /* loop for printing the array */
                  for(int i=0;i<length;i++){
                      cout<<arr[i]<<" ";          
                  }
                  return 0;
              }
              /* function for increasing the capacity of array */
              int* changeCapacity(int *arr, int length, int newCapacity) {
                  int *newArr = new int[newCapacity]; // definging a new array
      
                  if(length > newCapacity){ // checking if the length of the array is valid
                      cout<< "invalid length of array\n";
                      return NULL;
                  } else {
                      /* loop for transferring values to the new array */
                      for(int i = 0; i < length; i++){
                          newArr[i] = arr[i];
                      }
                      delete[] arr; // deleting the old array (clears the memory of the old array)
                      // arr = newArr; removed as this is not needed
                      return newArr; // returns the new array
                  }
              }
      
              /* function for adding a new element to the array */
              int* addElement(int *arr, int& length, int& capacity, int val){
              if(length >= capacity){ // checks if the array has space for storing the given value or not
                  capacity = capacity * 2; // doubles the capacity of the array
                  int* temp = changeCapacity(arr, length, capacity); // changes the size of the array to the new one
                  if(temp == NULL){ // checking if a null was returned
                      cout<< "Failed to change capacity\n";
                      return NULL; // returning  NULL
                  }
                  arr = temp; // the value of arr was not changed in your code (problem corrected)
                  arr[length] = val; // stores the value in the array
                  length += 1; // increasing the number of element count of the array
                  return arr; // returns the new array
              }else{
                  arr[length] = val; // stores the value in the array
                  length += 1; // increasing the number of element count of the array
                  return arr; // returns the new array
              }
              }
      

      【讨论】:

      • 这段代码也存在内存泄漏。问题中的同样错误。
      • 我认为最好预先为元素分配空间,而不是每次插入新元素时都为它们分配空间。这将要求您为每次插入遍历整个数组。我本可以使用链表或向量来解决这个问题,但考虑到这个问题,我认为最好保留问题的原始代码。此外,它还跟踪分配的内存。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 2017-02-20
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      • 1970-01-01
      相关资源
      最近更新 更多