Wyjątek w trakcie alokacji danych

Odpowiedz Nowy wątek
2017-01-11 13:46
Skromna Kura
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?

edytowany 1x, ostatnio: furious programming, 2017-01-11 16:30

Pozostało 580 znaków

2017-01-11 13:53
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

edytowany 3x, ostatnio: fasadin, 2017-01-11 13:54
Nie mów miałeś sytuację gdy ten const (2) kiedyś coś poprawił w catch, byłby to niezły wtf. - vpiotr 2017-01-11 14:22
nie mialem nigdy, ale const correctness w cpp jest dosc zwariowane, wiec na zimne dmucham ;) bo zaczalem sie zastanawiac co sie stanie gdy zostanie wyrzucony const obiekt czy zostanie zlapany przez normalny catch czy nie. - fasadin 2017-01-11 14:24

Pozostało 580 znaków

2017-01-11 14:00
Skromna Kura
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.

Pozostało 580 znaków

2017-01-11 14:08
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"

Pozostało 580 znaków

2017-01-11 14:12
Skromna Kura
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ąć?

Pozostało 580 znaków

2017-01-11 14:15
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
konkretnie tu: i < getNumberOfLayers()+20 - twonek 2017-01-11 14:28

Pozostało 580 znaków

2017-01-11 14:25
Skromna Kura
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.

Pozostało 580 znaków

2017-01-11 14:30
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

edytowany 1x, ostatnio: fasadin, 2017-01-11 14:32

Pozostało 580 znaków

2017-01-11 14:30
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.


PS: przegrałeś grę.

Pozostało 580 znaków

2017-01-11 14:56
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 ;)

Pozostało 580 znaków

2017-01-11 16:12
Skromna Kura
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.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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