2013-07-23 60 views
0

我有一個名爲Exception的異常類,我調用一個遞歸函數,在循環地圖時調用大約200次。 RecursiveFunction()是包含參數映射(將字符串映射到類參數)的類的一部分。類參數包含最小值,最大值和最小值和最大值之間的步數,以便可以使用每個參數集運行一組函數。 RecursiveFunction()因此循環遍歷映射以運行給定「當前」參數的一組函數。異常類失敗,遞歸函數

bool RecursiveFunction(map<string,param>::iterator current) { 
    map<string,param>::iterator last = parameters.end(); 
    last--; 
    if(current == last) 
     return true; 
    else { 
     // Do some things 
     if(something_wrong) 
      throw Exception("RecursiveFunction()","Something went wrong"); 
     ++current; 
     RecursiveFunction(current); 
    } 
} 

上述代碼在大約120次遞歸調用後失敗。這似乎是一個記憶的問題,因爲大部分時間它無法上線:

last--; 

奇怪的是,該代碼運行平穩,在以下兩種情況:

bool RecursiveFunction(map<string,param>::iterator current) { 
    ... 
    if(something_wrong) 
     throw ""; 
    ... 
    } 

bool RecursiveFunction(map<string,param>::iterator current) { 
    ... 
    if(something_wrong) { 
     Exception exc = Exception("RecursiveFunction()","Something went wrong"); 
     ThrowException(exc); //ThrowException() { throw exc; } 
    } 
    ... 
    } 

該代碼未觸及'throw',因此Exception沒有被構造或複製(通過斷點來確認)。爲什麼類的存在會影響函數的結果,如果該類沒有在函數中實例化?

編輯:

我能重現此通過完整的示例(與Visual Studio 2010):

#include <iostream> 

using namespace std; 

class Exception: public std::exception { 
private: 
    char  gsCallPath[1001]; 
    char  gsError[1001]; 
public: 
    Exception(const char* sErrorCallPath, const char* sThrownError) 
    { 
     strcpy(gsError,sThrownError); 
     strcpy(gsCallPath,sErrorCallPath); 
    } 
    ~Exception() { 
    } 
}; 

bool RecursiveFunction(int n); 

int main() { 
    RecursiveFunction(500); 
} 

bool RecursiveFunction(int n) { 

    cout << n << '\n'; 

    if (n == 0) 
     return true; 
    else { 
     if(false) { 
      throw Exception("",""); 
      //throw ""; 
     } 
     else 
     { 
      RecursiveFunction(n-1); 
     } 
    } 
} 

運行墜毀與堆棧溢出異常。用throw "";代替throw Exception("","");允許程序運行完成。注意:Exception類的大小會影響n溢出所需的大小。感謝@catscradle和@Yakk的評論。

+2

在代碼中,不清楚「參數」是什麼,函數是如何調用的,什麼是「做某些事情」,或者「something_wrong」是「真」。事實上,回答這個問題是不可能的。 –

+0

它以什麼方式「失敗」? (很可能,遞歸導致堆棧溢出;幸運的是,將它改爲使用迭代應該是微不足道的,除非您的實際代碼與您發佈的代碼非常不同)。 –

+0

參數被輸入到該功能。如果某些參數組合不正確,something_wrong爲真,例如參數[「population_output_min_age」] <參數[「START_YEAR」]。這是無關緊要的,因爲something_wrong沒有評估爲真。 – user1582665

回答

1
#include <exception> 
void f() { 
    if (false) { 
     throw ""; 
     //throw std::exception(); 
    } 
    return f(); 
} 
int main() { 
    f(); 
} 

看看程序集,看起來函數爲異常對象保留了堆棧空間,並且它是否被引發並不重要。因此,在""的情況下,該功能保留204字節(sub esp, 0CCh),在std::exception的情況下爲sub esp, 0D4h,即多8字節,即sizeof(std::exception) - sizeof(char*)

+0

謝謝。我添加了一個證明我不能在遞歸函數中使用Exception類的例子,因爲無論它是否被調用,它都被保留。使用ThrowException函數似乎是最好的解決方案。 – user1582665

+0

@ user1582665不知道最好。你確定你的遞歸總有一天不會變得更深嗎?我想你應該想出一個迭代算法。 – catscradle

+0

「最好」是我猜的一個相對的說法。我會重新考慮遞歸。再次感謝。 – user1582665