[英]Memory Allocation in Recursive C++ Calls
我在遞歸C ++程序中分配和釋放內存時遇到問題。 因此,如果不使用自動內存管理解決方案,我想知道是否有人可以幫我解決我遇到的內存泄漏問題。
以下代碼基本上解釋了問題(盡管這是一個人為的例子,請糾正我所犯的任何錯誤或簡化)。
一個數字類,用於保存數字的值:
class Number {
public:
Number() { value = 1; };
Number& operator + (const Number& n1) const {
Number result = value + n1.value;
return result;
};
int value;
};
執行遞歸的兩個函數:
Number& recurse(const Number& v1) {
Number* result = new Number();
Number one = Number();
*result = *result + recurse(one);
return *result;
}
int main(...) {
Number answer = Number();
answer = recurse(result);
}
正如你所看到的那樣,recurse函數中分配的內存被泄露了,但我不確定在哪里可以根據遞歸的性質釋放這些內存?
問題出在這里:
Number& operator + (const Number& n1) const {
Number result = value + n1.value;
return result;
};
你通過引用返回一個局部變量( result
),這是一個很大的NO-NO。 局部變量在堆棧上分配,當函數退出時,變量就消失了。 返回對局部變量的引用是將指針返回到現在用於其他東西的堆棧中,這將導致很多不良。
你應該做的是按值返回(只需將返回類型從Number&
更改為Number
)。 確保您有適當的復制構造函數,或者編譯器自動生成的復制構造函數適合您的需要。 這意味着當operator+
返回時,它會生成一個副本(通常可以通過優化),並且由於沒有涉及指針或引用,因此無法獲得損壞的返回值。
要修復內存泄漏,可以使用boost::shared_ptr
等智能指針。 或者,完全溝通指針和動態內存,只需從recurse()
返回值。
我不明白為什么你要在堆上分配內存開頭:
Number& recurse(const Number& v1) {
Number result;
Number one;
// I assume there is a step here to determine if the recursion should stop
result += recurse(one);
return result;
}
通過僅在堆棧上分配,可以保證在函數返回時清除變量。
否則我認為你必須使用某種智能指針。
所以除了返回Adam Rosenfield指出的局部變量的地址之外,我在代碼中還看到了其他三個問題。
首先,你的恢復功能永遠不會結束。 在recurse()的某個時刻,你必須檢查一個值,使它不再調用recurse()並返回。 這是遞歸的基本部分。 傳遞的參數v1也沒有被使用。
其次,運算符+()實際上不起作用。 沒有辦法將int分配給Number()對象。
第三,在main中傳遞一個名為result的東西,它永遠不會被聲明。
忘記這些錯誤,我假設您要分配堆上的所有對象以避免堆棧溢出,此函數將多次遞歸或者使用的實際對象比Number大得多。 在這種情況下,通過在recurse()內的堆上分配返回變量,您強制調用者刪除返回的對象。 因此,在recurse()和main()中調用recurse()之后,您必須刪除返回的值。 指示調用者的約定是返回指針而不是引用。 所以recurse()和main()看起來像這樣:
Number* recurse(const Number& v1) {
Number* result = new Number();
Number one;
if(v1.value >= 2) {
Number temp;
temp.value = v1.value - 1;
Number* partialResult = recurse( temp ); //capture the object to delete
*result = *partialResult + one;
delete partialResult; //delete the object
}
return result;
}
int main() {
Number result;
result.value = 15;
Number *answer;
answer = recurse(result);
delete answer;
}
注意:無論實際計算的是什么遞歸都是荒謬的。 我不知道意圖是什么,但它只是有用的東西。
您是否有動態分配內存的原因?
Number recurse(const Number& v1) {
Number result;
Number one;
retun result + recurse(one);
}
另外我注意到你沒有使用值v1
但最大的錯誤是遞歸沒有逃避條款。
這實際上是無限遞歸,基本上會耗盡內存。
聰明的指針是你的朋友。 至少快速閱讀auto_ptr。
另外,請閱讀Adam Rosenfield對您的其他問題的評論(返回對不存在的值的引用)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.