6

システムによって割り当てられたターゲットメモリgetaddrinfo()を取得するために呼び出す関数があります。多くの人が知っているように、getaddrinfo() によって割り当てられたメモリを解放するsockaddr*には、 を呼び出す必要があります。freeaddrinfo()

さて、私の関数には、いくつかの関数が失敗したために例外をスローする可能性のある場所がいくつかあります。私の最初の解決策は、freeaddrinfo()すべての if ブロックに を組み込むことでした。しかし、関数が戻る前にとにかくそれを呼び出さなければならなかったので、それは私には見苦しく見えました。

しかし、私が遭遇した問題は、スローステートメントを __try ブロックにコーディングすることが許可されていないことです。

次に、msdn を読み、throw ステートメントを __try ブロック内から呼び出されるヘルパー関数にスワップしようとしました...そしてほら、コンパイラはもうそれをうめきませんでした...

何故ですか?そして、これは安全ですか?これは私には意味がありません:/

コード:

void function()
{
    //...
    addrinfo* pFinal;
    __try
    {
        getaddrinfo(..., &pFinal);

        //if(DoSomething1() == FAILED)
        //  throw(exception);           //error C2712: Cannot use __try in functions that require object unwinding

        //but this works
        Helper();


        //...

    }
    __finally
    {
        freeaddrinfo();
    }
}


void Helper()
{
    throw(Exception);
}

編集:

以下を試してみましたが、整数をスローしても機能しますが、クラスを例外として使用すると機能しません:

class X
{
public:
    X(){};
    ~X(){};
};


void Helper()
{
    throw(X());
}


void base()
{
    __try
        {
            std::cout << "entering __try\n";

            Helper();

            std::cout << "leaving __try\n";
        }
        __finally
        {
            std::cout << "in __finally\n";
        }
};


int _tmain(int argc, _TCHAR* argv[])
{
    try
    {
        base();
    }
    catch(int& X)
    {
        std::cout << "caught a X" << std::endl;
    }

    std::cin.get();
    return 0;
}

なんで?:/

4

3 に答える 3

9

2つの例外タイプを混在させることはできません。裏では、C ++例外はSEHを使用し、SEH例外ハンドラーが例外伝播ロジックを台無しにする可能性があります。その結果、C++コンパイラではそれらを混在させることはできません。

PS:構造化例外処理は、ほとんどの場合、非常に悪い考えです。マイクロソフトは、非常に限られた状況を除いて、内部的にSEHの使用を禁止しています。構造化された例外処理を使用するコンポーネントは、自動的に徹底的なコードレビューの対象になります(コードをスキャンしてその使用法を探し、ケースを見逃さないようにするツールがあります)。

SEHの問題は、SEHを使用するときに、誤ってセキュリティの脆弱性を導入することが非常に簡単であるということです。

于 2011-07-15T15:30:46.850 に答える
3

getaddrinfoコンストラクタとfreeaddrinfoそのデストラクタを呼び出すクラスでaddrinfoをラップできます。

そうすれば、例外がスローされたかどうかに関係なく、常に解放されます。

于 2011-07-15T15:30:22.013 に答える
0
catch(int& X)
{
    std::cout << "caught a X" << std::endl;
}

それはキャッチしませんX、それはキャッチしint&ます。一致するcatchブロックがないため、例外はキャッチされず、スタックの巻き戻しは発生せず、__finallyハンドラーは実行されません。

スタックの巻き戻しが確実に行われるようにcatch (...)、スレッドエントリポイント(プライマリスレッド用)を配置できます。ただし、一部の例外は回復不能ですが、C++例外には当てはまりません。main()

于 2011-07-16T01:25:53.483 に答える