0

したがって、私はこの単純なCLIツールを作成しています。コードに煩わされることなく、基本的に次のようになります。

bool IsThing()
{
    // stuff goes here
    return false;
}

int _tmain(int argc, _TCHAR* argv[])
{
    bool IsThing_ = IsThing();
    if ( IsThing_ )
    {
        printf( "foo\n" );
        return 1;
    }

    return 0;
}

このコードを実行すると、明示的に失敗しようとします。IsThing()文字通り、を除くすべてのコードを削除しreturn falseます。ただし、毎回、必ず、戻りコード.を取得します1

デバッグするために、の本体で呼び出す直前にブレークポイントを内部IsThing()と直前に配置しました_tmain()。私を最も苛立たせているのは、内部のブレークポイントでIsThing()、VSが教えてくれることです

この行に実行可能コードは関連付けられていません。

代わりにメイン関数をステップスルーすると、文字通りに移動し、実際の関数にステップインすることなくbool IsThing_ = IsThing();if条件をチェックし、条件内にあるものにすぐにスキップします。

関数呼び出しが機能しないのはなぜですか?

4

2 に答える 2

2
bool IsThing()
{
    // stuff goes here
    return false;
}

int _tmain(int argc, _TCHAR* argv[])
{
    bool IsThing_ = IsThing();
    if ( IsThing_ )
    {
        printf( "foo\n" );
        return 1;
    }

    return 0;
}

リリース モードでは、Visual Studio はこのコードを次のように変換します。

int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

もちろん、IsThingは不要になったため、コードは生成されないため、ブレークポイントを設定することはできません。

ここで、実際に何かを行う関数 (ファイル I/O など) に十分なコードを詰め込み、 の戻り値をハードコーディングしない場合false、コンパイラは実際にそれを取得する関数にします。呼ばれた。しかし、最近のコンパイラは、「意味のある」ものを何も生成しないコードを排除することに長けています。

ここに大きなミステリーがあるとは思いません。それはコンパイラーの仕組みに過ぎません。

于 2013-03-11T20:50:24.223 に答える
1

/O1 または /O2 の最適化を使用する可能性が最も高いリリース構成でコンパイルしています。これは、コードを高速化し、サイズを小さくすることを目的としています。これは、コンパイル中にこの関数が次のことを意味します。

bool IsThing() { return false; }

インライン化されているため、main次と同等になります。

int _tmain(int argc, _TCHAR* argv[])
{
    bool IsThing_ = false;
    if ( IsThing_ )
    {
        printf( "foo\n" );
        return 1;
    }
    return 0;
}

または、ステートメントの本文さえif省略される可能性があり、次のようになります。

int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

これが、デバッグ構成で機能する理由でもあります。プロジェクトのプロパティに移動して、C/C++ -> 最適化の下で最適化オプションを変更Disabled (/Od)すると、この変更後にブレークポイントが機能することがわかるはずです:)

于 2013-03-11T20:52:53.150 に答える