2009-09-04 15 views
8

У меня есть некоторый код C++, который использует очень стандартный шаблон исключения:Почему мои исключения на C++ не попадают?

try { 
    // some code that throws a std::exception 
} 
catch (std::exception &e) { 
    // handle the exception 
} 

Проблема заключается в том, что исключения не поймали, и я не могу понять, почему.

Код компилируется в статическую библиотеку в OS X (через Xcode). Библиотека связана с приложением Cocoa с вызовом рассматриваемой функции через Objective-C++ thunk. Я подозреваю, что взаимодействие между Objective-C и C++ является виновником, но все мои попытки связать это провалились.

Я не смог создать простой пример, который воспроизводит это поведение в простом примере. Когда я беру соответствующий код из контекста моей большой программы, все работает.

Может кто-нибудь предположить, почему мои исключения не пойманы?

+1

Какие у вас есть доказательства того, что вы выбрали исключение? Какие у вас есть доказательства того, что это происходит из 'std :: exception'? (Не говорю, что вы ошибаетесь, но здесь нет четкой информации) –

ответ

-2

Спасибо за вклад от всех. Это хорошие предложения для тех, кто сталкивается с подобной проблемой. Он работает сейчас, но я не уверен на 100%, какие из различных изменений, которые я сделал, заставили все снова стать нормальными. Опять же, упрощение подхода к чему-то, что работает и построение резерва оттуда, окупилось.

Одна вещь, которая не упоминалась в ответах, и которая, как я думаю, была частью моей путаницы, заключается в том, чтобы убедиться, что обработчик делает очевидным, что на самом деле это исключение. Я думаю, что в некоторых моих формулировках обработчика он маскировал этот факт и передавал исключение на более высокий уровень обработчика.

15

Попробуйте блок catch(...) {}, посмотрите, действительно ли выбрано исключение.

+0

Я не понимаю этого ответа. Вопрос уже включает блок catch(). –

+3

В вопрос включен обработчик исключений типа 'std :: exception'. Блок catch с использованием эллипса (...) в качестве параметра catch поймает любое исключение независимо от типа исключения throw. Очень похоже на обработчик по умолчанию. –

3

я могу предложить две теории:

  1. исключение попадается, прежде чем он приходит на ваш пункт улова; любая функция в стеке может быть виновником. Как предлагает Майкл, попробуйте поймать все.
  2. Исключение исключения не находит ваш обработчик. Чтобы проанализировать это более подробно, вам нужно будет пройти код исключения, который очень волосатый. Посмотрите, помогает ли компиляция кода Objective-C с помощью -fobjc-exceptions.
1

Это может быть длинный снимок, но в настройках компилятора Visual Studio есть возможность полностью отключить исключения. Возможно, в GCC/XCode есть что-то подобное.

0

Исключения C++ могут быть примерно чем угодно, довольно часто char*. Как было предложено, добавьте catch (...), чтобы хотя бы разбить его и посмотреть, что происходит.

+2

Я никогда не видел исключение 'char *' и шлепнул бы того, кто использовал его –

7

Я подозреваю, что взаимодействие между Objective-C и C++ является виновником, но все мои попытки зафиксировать это провалились.

Возможно, вы правы, хотя его трудно отследить.

Во-первых, GCC явно does not allow you to throw exceptions in Objective C++ and catch them in C++ ("при использовании с Objective-C++, модель исключения Objective-C не взаимодействует с исключениями C++ в настоящее время. Это означает, что вы не можете @throw исключение из Objective-C и catch это в C++ или наоборот (то есть, throw ... @catch). ")

Однако, я думаю, что вы описываете случай, когда Objective C++ вызывает C++ код, код C++ бросает и вы надеетесь для кода C++ для поймать исключение. К сожалению, мне трудно найти документацию для этого конкретного случая. Есть надежда, потому что «It is believed to be safe to throw a C++ exception from one file through another file compiled for the Java exception model, or vice versa, but there may be bugs in this area». Если они могут сделать это для Java, есть шанс, что они могут сделать это для Objective C++.

По крайней мере, вам нужно указать -fexceptions во время компиляции («вам может понадобиться включить эту опцию при компиляции кода C, который должен правильно взаимодействовать с обработчиками исключений, написанными на C++»).Опять же, это не упоминает Objective C++, но может применяться.

5

Один из немногих известных gotcha с исключениями относится к доступу базового класса.

Если вы на самом деле бросаете класс, который происходит в частном порядке от std::exception, то обработчик std::exception не будет выбран.

Например:

#include <iostream> 

class A { }; 
class B : private A { } ; 

int main() 
{ 
    try 
    { 
    throw B(); 
    } 
    catch (A &) 
    { 
    std::cout << "Caught an 'A'" << std::endl; 
    } 
    catch (B &) 
    { 
    std::cout << "Caught an 'B'" << std::endl; 
    } 
} 

Обычно такой порядок обработчиков будет приводить к обработчику «B» никогда не выбирают, но в это случае dervies «B» от «A» в частном порядке, и так обработчик catch для типа «A» не рассматривается.

16

C++ allows you a variety of options for catching: value, reference or pointer. Обратите внимание, что этот код ловит только STD :: исключение передается по ссылке или значению:

try { 
    // some code that throws a std::exception 
} 
catch (std::exception &e) { 
    // handle the exception 
} 

Вполне вероятно, что исключение передается по указателю:

catch (std::exception* e) 

Проверить код который бросает исключение и видит, как он это делает.

Как указывает Марк, если вы поймаете по значению, а не по ссылке, вы рискуете нарезать свой объект.

+0

Спасибо - это только что зафиксировало мою проблему. –

+0

Рад это услышать, Бен Л! – Bill

+0

Этот ответ был отличной находкой, исходящей из фона языков java/scripting, естественно, что исключения всегда передаются по значению. Спасибо. – Cray

Смежные вопросы