Исключение С++ "Пропускает" предложение Try-Catch в MSVC x64

Я пишу программу на С++. Программа отлично работает для Win32 (x86), и недавно я попытался собрать ее изначально для x64. Конечно, материал сразу не работал.

После отладки проблемы мне удалось воспроизвести ее с помощью этого простого фрагмента кода:

class MyException { };

int main()
{
    try {
        for (;;) {
            try {
                std::cout << "Throwing" << std::endl;

                throw MyException();

                if (1 == 0) {
                    continue;
                }
            } catch (const MyException&) {
                std::cout << "Catch 1" << std::endl;
            }
        }
    } catch (const MyException&) {
        std::cout << "Catch 2" << std::endl;
    }

    std::cout << "Done" << std::endl;

    return 0;
}

(я скоро объясню предложение if (1==0))

При компиляции этого кода с использованием MSVC для x86 (я использовал 2010) результат будет таким, как ожидалось:

Throwing
Catch 1
Throwing
Catch 1
Throwing
Catch 1
Throwing
Catch 1
...

И так далее, в бесконечном цикле.

Однако компиляция этого кода для x64 приводит к:

Throwing
Catch 2
Done

Исключение полностью пропускает предложение внутреннего catch!

Это происходит только тогда, когда в моем коде существует предложение if (1 ==0). Когда я удаляю его, исключение попадает в "Catch 1", как ожидалось.

Я пробовал использовать другие компиляторы:

  • Эта ошибка также возникает в VS 2012.
  • MinGW и MinGW-w64 работают должным образом.

Мой вопрос: это ошибка MSVC, или это какое-то поведение undefined в С++, которое мне не хватает? Если это действительно ошибка MSVC, я хотел бы услышать некоторое понимание причины.

Спасибо.

Ответ 1

Эта ошибка может иметь какое-то отношение к оптимизации компилятора - интересно, что компоновщик выйдет из строя в вашей версии сборки (когда теоретически будет включена полная оптимизация).

У вашей отладочной сборки оптимизация полностью отключена (/Od)?

Справка Visual Studio также содержит инструкцию (в разделе "Оптимизация наилучшей практики" ), препятствующая блоки try/catch в 64-битном коде.

Если вы отключите оптимизацию в сборке релизов, компоновщик не сработает. Он также не будет разбиваться (но будет воспроизводить плохое поведение), если вы удалите только инструкцию "продолжить".

if (1==0) {
//continue;
}

Ответ 2

Попробуйте переключатель переключателя /FA:

http://msdn.microsoft.com/en-us/library/367y26c6%28v=vs.80%29.ASPX

где-нибудь в "дополнительном выходном файле" в ваших "настройках компилятора". (убедитесь, что все остальные настройки являются именами)

Затем сделайте разницу между обоими выходами. разместите здесь diff. Я уверен, что некоторые люди смогут рассказать вам, почему и как, и, возможно, некоторые настройки компилятора или обходные пути кода.