0

Exception という例外クラスがあり、マップのループ中に約 200 回呼び出される再帰関数を呼び出しています。RecursiveFunction() は、パラメーター マップ (文字列をクラス パラメーターにマップする) を含むクラスの一部です。クラス param には、最小値、最大値、最小値と最大値の間のステップ数が含まれているため、各パラメーター セットで一連の関数を実行できます。したがって、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 "";、プログラムを最後まで実行できました。注: 例外クラスのサイズは、オーバーフローするために必要な 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) が予約され、その場合は8 バイト多く、つまり が予約されます。std::exceptionsub esp, 0D4hsizeof(std::exception) - sizeof(char*)

于 2013-07-23T14:05:48.267 に答える