2013-07-23 62 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