Wyjątek w trakcie alokacji danych

0

Witam. Chcę użyć wyjątku typu bad_alloc w trakcie wykonywania alokacji danych w mojej tablicy. Całość zaprogramowałem jak poniżej:

 void perceptron::allocate()
{
	try {
		O = new float*[getNumberOfLayers()];
		for (int i = 0; i < getNumberOfLayers(); i++)
		{
			O[i] = new float[getN(i)];
			for (int j = 0; j < getN(i); j++)
			{
				setO(i, j, 0);
			}
		}
	}

	catch (bad_alloc& ba){
		cerr << "Exception bad_alloc catch: " << ba.what() << endl;
	}
}

Więc w momencie tworzenia wyjątku powinna pojawić się wydruk typu:

 Exception bad_alloc catch: bad allocation

Zamiast tego pojawia się komunikat o nieobsługiwanym wyjątku (ale dlaczego?), gdzie standardowo do wyboru jest opcja kontynuacji, albo przerwania, do tego stos błędów. Ma ktoś pomysł, dlaczego wyjątek nie jest obsługiwany?

0
  1. Sprobuj zlapac wszystkie exceptiony (tak zwane catch them all... pokemon) zobacz czy wtedy Ci zlapie wyjatek
  2. sprobuj catch (const std::bad_alloc& e)
  3. uzyj tam std::bad_alloc moze masz jakies dziwne przeladowanie tego
  4. moze masz wyjatek wczesniej zanim wystapi bad_alloc
0

Zaprogramowałem całość następująco:

 void perceptron::allocate()
{
	try {
		O = new float*[getNumberOfLayers()];
		for (int i = 0; i < getNumberOfLayers()+20; i++)
		{
			O[i] = new float[getN(i)];
			for (int j = 0; j < getN(i); j++)
			{
				setO(i, j, 0);
			}
		}
	}

	catch (const std::bad_alloc& e){
		cerr << "Exception bad_alloc catch: " << e.what() << endl;
		system("pause");
	}

	catch (...) {
		cout << "Exception: bad allocate.";
		system("pause");
	}
}

Pojawia się dokładnie to samo, niestety. Jak usunę "+20" i nie wyskoczy poza możliwą liczbę sieci, to program kompiluje się poprawnie, więc wyjątek jest na pewno w bloku "try". Dziwne, że nic nie jest łapane.

0

jezeli

catch (...)

nie lapie nic, to bladem nie jest wyrzucanie wyjatku. Zapewne starasz sie zrobic cos z pamiecia ktora nie nalezy do Ciebie i program po prostu sie crashuje. Musisz debbugowac te swoje metody i wylapac kiedy sie "wywala"

0

Właśnie tak. Chciałem zaprogramować wyjątki w sytuacji, kiedy przekraczam dopuszczalną wartość tablicy (w cpp dosyć często mi się zdarza). Rozumiem, że nie da się tego w wyjątki ująć?

1

co innego jest za duza alokacja, co wtedy zostanie rzucony wyjatek. U Ciebie blad jest inny bo gdyby to sie stalo to bys dostal wyjatek.

Gdzies w kodzie masz UB na podobnej zasadzie jak to

 array = new float[10];
 array[10] = 4.3; // to jest UB bo wyszedlem po za zakres tablicy. W tym momencie program moze, ale nie musi sie wywalic
0

Rozumiem. Swoją drogą: są wyjątki, które mogę zaprogramować, jak wyskoczę poza zakres poprawnie wcześniej zaalokowanej tablicy? Wróćmy póki co do alokowania:

 try {
		O = new float*[getNumberOfLayers()];
		for (int i = 0; i < getNumberOfLayers(); i++)
		{
			O[i+4] = new float[getN(i)];
			for (int j = 0; j < getN(i); j++)
			{
				setO(i, j, 0); // jako inputy/outputy wpiszmy początkowo same zera
			}
		}
}

	catch (const std::bad_alloc& e){
		cerr << "Exception bad_alloc catch: " << e.what() << endl;
		system("pause");
	}

Teraz powinien bankowo pojawić się błąd z alokacją: chcę przypisać pamięć do 5 obiektu, przy czym "getNumberOfLayers()" jest ustawione na 2. Faktycznie: wywala wyjątek, ale znowu nieobsługiwany. I jak tutaj temu zaradzić? Co do sytuacji, którą przytoczyłeś: póki co wszystko poprawnie zaimplementowałem i po prostu testuję zachowanie wyjątków dla różnych sytuacji :). Jak nie wciskam nigdzie za dużych rozmiarów tablicy, program poprawnie się kompiluje.

0

do testowania (ze nie jest lapany wyjatek) miec
catch(...)
jezeli on Ci nie wylapie wyjatku to znaczy ze wyjatek nie zostal wyrzucony i blad jest gdzie indziej

jak wyskoczę poza zakres poprawnie wcześniej zaalokowanej tablicy?
Nie, ale mozesz uzyc std::array czy std::vector i wtedy powinno byc (musialbys poczytac w dokumentacji, nie pamietam czy te klasy rzucaja wyjatek jak wyjdzie sie po za zakres).

Jak tworzysz za duza tablice dynamicznie to powinienes dostac bad_alloc

#include <iostream>
#include <new>
 
int main()
{
    try {
        while (true) {
            new int[100000000ul];
        }
    } catch (const std::bad_alloc& e) {
        std::cout << "Allocation failed: " << e.what() << '\n';
    }
}

ten kod dziala http://ideone.com/CX9OAt, sprawdz u siebie rowniez

0

są wyjątki, które mogę zaprogramować, jak wyskoczę poza zakres poprawnie wcześniej zaalokowanej tablicy

Nie, jeśli korzystasz ze 'zwykłych' tablic, ale na przykład metoda at z kontenera std::vector dokonuje sprawdzania zakresu.

1
[Skromna Kura napisał(a)]

Teraz powinien bankowo pojawić się błąd z alokacją: chcę przypisać pamięć do 5 obiektu, przy czym "getNumberOfLayers()" jest ustawione na 2. Faktycznie: wywala wyjątek, ale znowu nieobsługiwany. I jak tutaj temu zaradzić? Co do sytuacji, którą przytoczyłeś: póki co wszystko poprawnie zaimplementowałem i po prostu testuję zachowanie wyjątków dla różnych sytuacji :). Jak nie wciskam nigdzie za dużych rozmiarów tablicy, program poprawnie się kompiluje.

Mylisz pojęcia. Błąd alokacji jest wtedy gdy system nie jest w stanie dać Ci tyle pamięci ile byś chciał. Latanie po "nieswojej" pamięci nie ma z tym nic wspólnego.
Posłuchaj rady @Patryk27 i użyj std:vector. IMHO bad_alloc w dzisiejszych czasach(x64) to albo ostra fragmentacja albo wepchanie do ramu nadmiarowych danych, z których i tak się nie korzysta. Czyli tak czy siak - wina programisty ;)

0

W porządku, dzięki za odpowiedzi:). W takim razie będę korzystał z wyjątków tylko związanych z błędną alokacją (oczywiście, jeśli mowa o samej alokacji). Zapytałbym jeszcze, czy wie ktoś, jak rozwiązać problem nieodświeżającego się Visuala? Nieraz pokazuje błąd, który po poprawieniu kodu już dawno nie powinien istnieć. Wówczas włączam i wyłączam go ponownie, po czym eureka, nagle problemu nie ma. Tak jak gdyby miał jakieś cache, które automatycznie by odpalał po określonym czasie. I o ile nie zajdą znaczące zmiany w kodzie, będzie je odpalał do woli.

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