【问题标题】:Memory leaks passing dynamic variables recursively递归传递动态变量的内存泄漏
【发布时间】:2014-01-28 09:15:54
【问题描述】:

我有一个递归函数,每次调用该函数时都需要创建一个新数组。该函数还需要之前创建的数组:

void myFunc(int* prevArray)
{
int newSize;
//do some calculations to find newSize
int* newArray;
newArray = new int[newSize];
//do some calculations to fill newArray
//check some stopping condition
myFunc(newArray);
}

这个函数会泄漏内存,但我无法通过添加来避免这种情况

删除[] newArray;

因为我只能在再次调用该函数后添加它。我该如何解决这个问题?

【问题讨论】:

  • 在调用myFunc之后做delete[] newArray;有什么问题?
  • 好吧,只要递归继续进行,它就会一直堆积内存。数组相当大,我需要经常调用这个函数。
  • 你可以删除prevArray,除非它等于nullptr。
  • @RobVerheyen 好吧,这似乎是您算法的自然结果 - 每次连续调用 myFunc 都需要一个由前一次调用计算的大数组。
  • 不会从前一个实例中复制 prevArray 吗?

标签: c++ recursion memory-leaks


【解决方案1】:

您可以通过使用动态内存分配来解决这个问题。

// allocate initial size
const int INITIAL_SIZE = 5;
int *myArray = malloc(sizeof(int) * INITIAL_SIZE));

int myFunc(int *aArray, int numAllocated) {
    int numElements = calculateNewSize();

    if (numElements != numAllocated) {
        // allocate new size
        realloc(aArray, (numElements * sizeof(int));
    }

    return numElements;
}

现在您可以像这样调用 myFunc:

int numElements;

numElements = myFunc(myArray, numElements);

使用完 myFunc 后,别忘了释放内存

free(myArray);

【讨论】:

  • 这似乎是一个很好的解决方案,但问题是 newArray 的内容取决于 prevArray 的内容。我知道 realloc 保留了旧内存块中的所有内容,但我的 newArray 不仅仅是我的旧数组,最后添加了一些东西。它们表示在它们之间完成了一些线性代数的矩阵。
  • 我没看出问题,那你为什么不初始化数组呢?元素的数量是给定的变量,因此很容易编写一个初始化函数来迭代所有元素。
【解决方案2】:

试试类似的东西

void myFunc(int* prevArray)
{
    int newSize;
    ...newArray = new int[newSize];
    myFunc(newArray);
    delete[] newArray;
}

或者更好的是使用 std::unique_ptr 来控制 newArray 内存。通过这种方式,您将遵循有关动态内存的经验法则 - 它应该有一个所有者,负责分配和释放它。

【讨论】:

    【解决方案3】:

    您可能只是使用向量并将新结果交换为最终结果。

    #include <iostream>
    #include <vector>
    
    struct X { ~X() { std::cout << "Destruction\n"; } };
    void recursive(unsigned n, std::vector<X>& result) {
        // Put new_result in a scope for destruction
        {
            std::vector<X> new_result(1);
    
            // Do something
    
            // The previous result is no longer needed
            std::swap(result, new_result);
        }
    
        // Next recursion
        if(n) {
            std::cout << "Call\n";
            recursive(--n, result);
        }
    }
    
    int main() {
        std::vector<X> result(1);
        std::cout << "Call\n";
        recursive(3, result);
        return 0;
    }
    

    【讨论】:

    • 我不完全确定我是否理解您的意思。结构是否意味着包含我的数组?
    • 不,它的目的只是为了显示删除点 - std::vector 将是您的选择
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 2012-08-31
    • 2021-07-11
    • 2010-11-04
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    相关资源
    最近更新 更多