[C++ BCB 2007] Abnormal program term.. w catch(...)

0

Witam,

mam funkcje w której jest blok try. Podczas błędu wywołuję throw i łapię w catch(...). I wyskakuje mi mb Abnormal program termination i programo finito.

Dlaczego, gdy zamiast pustego throw'a daję throw x (x to liczba całk) i łapię przez catch(int x) to jest ok?

W poście: http://4programmers.net/Forum/475612?h=resource%20type#id475612 MarekR22 napisał mi, że

stosowanie "catch( ... )" też nie jest zalecane
. Dlaczego?

0
  1. Bo to łapie wszystko a zwykle nie nie powinno się wszystkiego łapać
  2. bo nie da się ustalić co to właściwie było
  3. z powodu 1 i 2 to jest sprzeczne z konwencjami kodowania. Zwykle catch( ... ) powinno być tylko w main tak na wszelki wypadek jeśli by poleciało coś nieoczekiwanego.

throw TypProsty też jest nie zalecane bo niesie ze sobą mało inforamcji, zwykle praktykuje się rzucanie wyjątków dziedziczących po jakiejś klasie bazowej, popatrz na kody automatycznie generowane przez różne środowiska i jakie wyjątki rzucają różne biblioteki.

0

Ok, to na temat stylu programowania. A dlaczego wyskakuje "Abnormal..."?

0

wyobraz sobie throw; jako throw-void i co sie stanie jesli implementacja catch(...) zaklada ze cos bedzie rzucone

0

Chcialem napisac, ze nie masz racji. Ale sprawdzilem i prawda :(
Jezeli wyrzucisz "throw" to catch(...) tego nie zlapie.

W takim razie moje pytanie, jak zlapac taki wyjatek?

0

Hmm: http://www.cplusplus.com/doc/tutorial/exceptions.html
...It is also possible to nest try-catch blocks within more external try blocks. In these cases, we have the possibility that an internal catch block forwards the exception to its external level. This is done with the expression throw; with no arguments. For example:

try {
  try {
      // code here
  }
  catch (int n) {
      throw;
  }
}
catch (...) {
  cout << "Exception occurred";
}
0

quetzalcoatl miał na myśli trochę co innego.
Pomyśl nad:

int main() {
    try {
	std::cout << "rzucam wyjątek" << "\n";
	throw;
    }
    catch(...) {
	std::cout << "wyjątek" << "\n";
    }
    std::cout << "poza try-catch" << "\n";
    
    return 0;
}

Wyświetli się "rzucam wyjątek" i program się zakończy.

Edit: Różnica jest taka, że throw nie jest w catch { }

0

Różnica jest taka, że throw nie jest w catch { }

że niby catch(...) wie, że throw był rzucony z bloku catch(arg) i wtedy łapie, a jak z czystego bloku try to już nie złapie??? Eeeee...

0

Jeżeli użyjesz throw w bloku catch, to zostaje rzucony (propagowany) wyjątek, który został złapany przez to catch. Taki skrót ;-)

Zostanie on dalej obsłużony, bo wyjątek nie jest pusty. Czyli do catch(...) na pewno się dopasuje.

w przypadku samego throw, poza catch, zostaje rzucony wyjątek "pusty". W pewnych implementacjach nie jest łapany przez catch(...), które oczekuje, że wyjątek będzie miał "zawartość".

Nie wiem czy są implementacje, które łapią wyjątki puste.

0

Nie spotkałem się jeszcze z sytuacją gdzie ktoś by rzucał pusty wyjątek.

0

Obserwuje i obserwuje ten wątek i nikt nie widzi w czym problem.
W końcu mnie to wkurzyło i oto program demonstrujący o co chodzi z tym thow;:

#include <iostream>

using namespace std;

class CleanStackLog
{
	const char* text;
public:
	CleanStackLog( const char* logText ):text( logText )
	{
		cout << "Creating: " << text << endl;
	}

	CleanStackLog( const CleanStackLog& source ):text( source.text )
	{
		cout << "Coping: " << text << endl;
	}

	~CleanStackLog()
	{
		cout << "Destroying: " << text << endl;
	}
};

void ThrowTest()
{
	CleanStackLog info( "Rethrowing" );
	throw;
}

int main(void)
{
	cout << "Start" << endl;
	try
	{
		CleanStackLog trying1( "try 1");
		try
		{
			CleanStackLog trying1( "try 2");
			throw CleanStackLog( "Thrown object" );
		}
		catch ( int e )
		{
			cout << "Unreachable e = "<< e << endl;
		}
		catch ( CleanStackLog& e )
		{
			cout << "First throw and catch was successful" <<endl;
			ThrowTest();
		}
	}
	catch ( int e )
	{
		cout << "Unreachable e = "<< e << endl;
	}
	catch ( CleanStackLog& e )
	{
		cout << "Rethrow and catch was successful" <<endl;
	}

	try
	{
		CleanStackLog trying1( "try 3");
		ThrowTest();
	}
	catch ( ... )
	{
		cout << "Empty catch" << endl;
	}
	cout << "Stop" << endl;
}

Na ekranie pojawia się:

Start
Creating: try 1
Creating: try 2
Creating: Thrown object
Destroying: try 2
First throw and catch was successful
Creating: Rethrowing
Destroying: Rethrowing
Destroying: try 1
Rethrow and catch was successful
Destroying: Thrown object
Creating: try 3
Creating: Rethrowing

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Jeśli ktoś jeszcze nie rozumie o co chodzi to wyjaśniam. throw; oznacza rzuć ponownie wyjątek. Czyli to może się pojawić TYLKO wewnątrz bloku catch. Kompilator nie wykrywa tego ponieważ dopuszczalne jest ponowne rzucanie wyjątku z wnętrza metody, co doskonale widać z załączonego powyżej kodu i otrzymanego wyniku.

Po tym to już musi być END OF TOPIC.

0

tak, to mialem na mysli, tylko 'nie-do-rozwinalem' mysli jak nalezy, przepraszam;)

0

Po tym to już jest END OF TOPIC. W zasadzie wystarczyłoby

throw; oznacza rzuć ponownie wyjątek.

Dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1