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; }
    }
    ...
   }

代码没有命中“抛出”,因此没有构造或复制异常(用断点确认)。如果该类没有在函数中实例化,为什么类的存在会影响函数的结果?

编辑:

我能够使用一个完整的示例(使用 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 Exception("","");throw "";允许程序运行完成。注意:Exception 类的大小会影响 n 需要多大才能溢出。感谢@catscradle 和@Yakk 的评论。

4

1 回答 1

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*)

于 2013-07-23T14:05:48.267 回答