2009-09-04 17 views
8

Mam kod C++, który używa bardzo standardowy wzór wyjątek:Dlaczego nie są przechwytywane wyjątki C++?

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

Problem polega na tym, że wyjątki nie są złapany i nie mogę zrozumieć, dlaczego.

Kod kompiluje się do biblioteki statycznej w OS X (przez Xcode). Biblioteka jest połączona z aplikacją Cocoa, z wezwaniem do funkcji, o której mowa, za pośrednictwem odgłosu Objective-C++. Podejrzewam, że przyczyną jest interakcja między Objective-C i C++, ale wszystkie moje próby zlikwidowania tego nie powiodły się.

Nie udało mi się stworzyć prostego przykładu, który odtwarza to zachowanie w prostym przykładzie. Kiedy wyjmuję odpowiedni kod z kontekstu mojego wielkiego programu, wszystko działa.

Czy ktoś może zasugerować, dlaczego moje wyjątki nie zostały przyłapane?

+1

Jaki masz dowód na to, że uważasz, że rzuca się wyjątek? Jakie masz dowody, które wynikają z 'std :: exception'? (Nie mówię, że się mylisz, ale jest tu wyraźny brak informacji) –

Odpowiedz

-2

Dzięki za wiadomość od wszystkich. To są dobre sugestie dla każdego, kto ma podobny problem. Działa to teraz, ale nie jestem w 100% pewna, które z różnych zmian, które wprowadziłem, sprawiły, że znowu staną się zdrowe. Po raz kolejny opłaciło się podejście polegające na uproszczeniu do czegoś, co działa i buduje z powrotem.

Jedną z rzeczy, o której nie wspomniałem w odpowiedziach i która, jak sądzę, była częścią mojego zamieszania, jest upewnienie się, że przewodnik pokaże, że faktycznie złapał wyjątek. Myślę, że w niektórych z moich sformułowań tego programu maskował ten fakt i przekazywał wyjątek do obsługi wyższego poziomu.

15

Spróbuj bloku catch(...) {}, zobacz, czy wyjątek jest rzeczywiście zgłaszane.

+0

Nie rozumiem tej odpowiedzi - pytanie już zawiera blok catch(). –

+3

Pytanie zawiera procedurę obsługi wyjątków typu "std :: exception". Blok catch wykorzystujący elipsę (...) jako parametr catch będzie wychwytywał każdy wyjątek bez względu na typ wyjątku throw. Podobnie jak "domyślny" handler. –

3

mogę zaoferować dwie teorie:

  1. wyjątek wplątuje przed chodzi swój klauzuli catch; każda funkcja na stosie może być sprawcą. Jak Michael proponuje, spróbuj złapać wszystko.
  2. rozwijanie wyjątków nie udaje się zlokalizować programu obsługi. Aby przeanalizować to bardziej szczegółowo, musiałbyś przejść przez wyjątek rozwijający kod, który jest bardzo owłosiony. Sprawdź, czy pomocne jest skompilowanie kodu Objective-C z -fobjc-exceptions.
1

To może być długie ujęcie, ale w ustawieniach kompilatora Visual Studio istnieje opcja całkowitego wyłączenia wyjątków. Być może jest coś podobnego w GCC/XCode.

0

Wyjątki C++ mogą być praktycznie dowolne, często jest to char*. Zgodnie z sugestią, dodaj co najmniej jedną przerwę i zobacz, co się dzieje.

+2

Nigdy nie widziałem wyjątku "char *" i uderzyłbym, ktokolwiek użył. –

7

Podejrzewam, że przyczyną jest wzajemne oddziaływanie między Objective-C i C++, ale wszystkie moje próby zlikwidowania tego nie powiodły się.

Prawdopodobnie masz rację, chociaż trudno je wyśledzić.

Najpierw GCC wyraźnie does not allow you to throw exceptions in Objective C++ and catch them in C++ ("używane z Objective-C++, model wyjątek Objective-C nie współpracować z wyjątków C++ w tym czasie. Oznacza to, że nie może @throw wyjątek z Objective-C i catch to w C++ lub odwrotnie (tzn throw ... @catch). ")

jednak myślę, że opisując przypadek gdzie Objective C++ nazywa kodu C++, kod C++ rzuty i masz nadzieję, że do kodu C++ do wychwycić wyjątek. Niestety mam trudności ze znalezieniem dokumentacji dla tego konkretnego przypadku. Jest pewna nadzieja, ponieważ "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." Jeśli mogą zrobić to dla Javy, jest szansa, że ​​mogą to zrobić dla Objective C++.

Przynajmniej musisz określić -fexceptions w czasie kompilacji ("może być konieczne włączenie tej opcji podczas kompilowania kodu C, który musi współpracować poprawnie z procedurami obsługi wyjątków napisanymi w C++").Ponownie, to nie wspomina konkretnie o Objective C++, ale może mieć zastosowanie.

5

Jeden mało znany grosz z wyjątkami odnosi się do dostępu do klasy bazowej.

Jeśli faktycznie rzucasz klasę, która pochodzi prywatnie z std::exception, wówczas obsługa std::exception nie zostanie wybrana.

Na przykład:

#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; 
    } 
} 

Zazwyczaj taka kolejność koparki skutkowałyby obsługi „B” nie jest wybrany, ale w to przypadku dervies „B” z „A” prywatnie a więc program obsługi catch dla typu "A" nie jest brany pod uwagę.

16

C++ allows you a variety of options for catching: value, reference or pointer. Zauważ, że ten kod łapie tylko std :: wyjątki przekazywane przez referencję lub wartość:

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

Jest wielce prawdopodobne, że wyjątek jest przekazywana przez wskaźnik:

catch (std::exception* e) 

sprawdzić kod to jest wyrzucanie wyjątku i zobaczenie, jak to robi.

Jak zaznacza Mark, jeśli złapiesz według wartości, zamiast odniesienia, ryzykujesz cięcie swojego obiektu.

+0

Dziękuję - to właśnie naprawiło mój problem. –

+0

Miło to słyszeć, Ben L! – Bill

+0

Ta odpowiedź była świetnym znaleziskiem, pochodzącym z języków java/języków skryptowych. Naturalnie zakłada się, że wyjątki są zawsze przekazywane wartością. Dzięki. – Cray

Powiązane problemy