Dynamiczna tablica dwuwymiarowa - problem z inicjalizacją

0
 
#include <iostream>
using namespace std;
int main()
{
    unsigned short W, K; //W - liczba wierszy
    cin >> W >> K;       //K - liczba kolumn
    int **tab=new int *[W];
    cout << "\n";
    for(unsigned short i=0;i<K;i++)
    {
        tab[i]=new int[K];
    }
    unsigned short n=1;
    //inicjalizacja
    for(unsigned short i=0;i<W;i++)
    {
        for(unsigned short j=0;j<K;j++)
        {
            tab[i][j]=n;
            n++;
        }
    }
    //wyswietlanie
    for(unsigned short i=0;i<W;i++)
    {
        for(unsigned short j=0;j<K;j++)
        {
            cout << tab[i][j] << "\t";
        }
        cout << "\n\n";
    }
    //usuwanie
    for(unsigned short i=0;i<K;i++)
    {
        delete [] tab[i];
    }
    delete [] tab;
    return 0;
}

Gdy podaję na wejście liczby o równych wartościach, np. 5 i 5, to jest ok (http://ideone.com/HYp19). Problem zaczyna się w przypadku różnych wartości, np.:

#5 i 7, wtedy Windows raportuje błąd po wyświetleniu zawartości tablicy. Przykład: http://ideone.com/FnBlr
#7 i 5, wtedy jest błąd jest raportowany przy inicjalizacji tablicy. Przykład: http://ideone.com/9wj4b
#9 i 6, podobnie jak w poprzednim punkcie.

Program kompiluje się i uruchamia bez problemu.

1
cin >> W >> K;       //K - liczba kolumn
int **tab=new int *[W];
cout << "\n";
for(unsigned short i=0;i<K;i++) // powinno byc do W, bo tyle na poczatku alokujesz
{
    tab[i]=new int[K];
}
0

Jest ok, rozumiem błąd. Teraz pytanie czy dobrze rozumiem napisany przez siebie kod :)
Chodzi mi o trochę trudniejsze fragmenty.

int **tab=new int *[W];

Od lewej. Tworzę wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

for(unsigned short i=0;i<K;i++){ tab[i]=new int[K];}

Każdemu elementowi tablicy W-wymiarowej przypisuję wskaźnik na nową tablicę K-wymiarową.
W ten sposób uzyskuję dynamiczną tablicę dwuwymiarową.

for(unsigned short i=0;i<K;i++){delete [] tab[i];}

Usuwam wcześniejsze przypisania wskaźników do tablicy W-wymiarowej.

delete [] tab;

Usuwam wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

1
cichociemny napisał(a):
int **tab=new int *[W];

Od lewej. Tworzę wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

Tworzysz wskaźnik do wskaźnika na int nazwany tab, alokujesz tablicę wskaźników (int*) długości W i inicjalizujesz tab tak, aby wskazywał na początek zaaokowanej tablicy.

cichociemny napisał(a):
for(unsigned short i=0;i<K;i++){ tab[i]=new int[K];}

Każdemu elementowi tablicy W-wymiarowej przypisuję wskaźnik na nową tablicę K-wymiarową.
W ten sposób uzyskuję dynamiczną tablicę dwuwymiarową.

Każdemu z W wskaźników do int w tablicy tab przydzielasz tablicę int długości K.

cichociemny napisał(a):
for(unsigned short i=0;i<K;i++){delete [] tab[i];}

Usuwam wcześniejsze przypisania wskaźników do tablicy W-wymiarowej.

Zwalniasz pamięć przydzieloną w poprzedniej pętli do każdego z elementów tablicy tab. Każdy z tych elementów jest wskaźnikiem na int i wskazuje blok pamięci przydzielony operatorem new[] – każdy z tych bloków to tablica int[K].

cichociemny napisał(a):
delete [] tab;

Usuwam wskaźnik na tablicę wskaźników na tablicę W-wymiarową.

Zwalniasz główną tablicę tab.

Ważna jest tu kolejność, bo tak naprawdę tab jest wskaźnikiem na początek bloku pamięci, podobnie jak każdy element w tab. Jeśli zwolnisz od razu główną tablicę, stracisz możliwość odwołania się do podtablic, co skutkuje memleakiem.

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