[C++] Tablice dynamiczne, usuwanie i obszar pamieci

0

Witam,
Za pomoca ponizszego programuj stworzyłem tablice dynamiczna, nastepnie wyświetlam ja oraz chce ja usunac a potem upewnic sie czy aby na pewno zostala usunieta.

Na poczatek pytanie: Czy jestli usuwam ta tablice w taki sposob : delete[] (oraz ustawiam NULL na jej poczatek ( trzeba tak ?) ) to ja niszcze tylko wskazniki do jej poczatku czy tez ogolnie wartosci tej tablicy ?

Bo wg mojego programu, napisanego zreszta chyba dobrze dane tablicy caly czas zostaja w pamieci operacyjnej. A chyba nie powinny, co ? Jesli sie myle to niech mnie ktos poprawi.

A doszedlem do tego wniasku za pomoca dodatkowego wskanika 'wsk' ktory na poczatku zostal przypisany do mojej tablicy i juz po jej 'usunieciu' przeszukuje forem pamiec a tam niespodzianka - moja stara usunieta tablica jest tam nadal (no poza poczatkowym elementem ktory zostal ustawiony an NULL).

Ogolnie rozchodzi sie o to czy ta liczby po usunieciu tabicy nadal tam sa i usuniete jest tylko wskazanie do poczatku obszaru od ktorego sie zaczynaja czy tez nie powinny byc one wykasowane oraz obszar ten powinien zawierac .. wlasnie - co powinien zawierac, NULL ?

Mam nadzieje ze wystarczajaco jasno sie rozpisalem. Dziekuje z gory za zainteresowanie ;-)

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <ctime>
#include <new>


using namespace std;


int main()
{
    srand (static_cast<unsigned>(time(NULL)));
    // tworz
    int *tab;
    tab = new int[10];
    if (tab == NULL)
        cout << "Niestety, zabraklo pamieci!";
    // ustaw
    for(int i = 0; i < 10 ; i++)
        tab[i] =rand();

    int *wsk = tab;

    // pokaz
    for(int i = 0; i < 10 ; i++)
        cout << "tab["<<i<<"] = " << tab[i]<<"\n";
    // usun
    delete[] tab;
    tab = NULL;
    // pokaz
    cout << "Po usunieciu: \n";
     if(tab == NULL) cout << "Nic tu nie ma\n";
    else
    {
    for(int i = 0; i < 10 ; i++)
        cout << "tab["<<i<<"] = " << tab[i]<<"\n";
    }
    //cout<<"pokaz wsk = " << *wsk;
      for(int i = 0; i < 10 ; i++)
        cout << "tab["<<i<<"] = " << *(wsk + i)<<"\n";

getch();
return 0;
}
0

delete usuwa wskaźniki nie wartości. Jeśli chcesz usunąć wartość to zmień ją sobie na 0.

wsk[1] = 0;
wsk[2] = 0;

delete [] wsk;

NULL = 0

Krolik napisał(a)

odczyt zwolnionej pamięci może spowodować błąd, ale nie musi, tak samo jak zapis zwolnionej pamięci MOŻE, ale nie MUSI. OS zwykle przydziela pamięć całymi stronami, więc jeśli dana strona jest we władaniu procesu, to zapis do nieprzydzielonego fragmentu strony nie musi spowodować błędu.

0

Co to za sprawdzanie, czy wskaźnik jest nullptrem po new[]? W C++ new, jak coś się nie uda, nie zwraca nullptra, tylko robi znacznie gorsze rzeczy (rzuca wyjątek, którego w sumie zwykle nie ma co łapać, bo skoro jest OOM to program i tak by poszedł w buraki).

0

Co to za sprawdzanie, czy wskaźnik jest nullptrem po new[]? W C++ new, jak coś się nie uda, nie zwraca nullptra, tylko robi znacznie gorsze rzeczy (rzuca wyjątek, ...)

Kiedyś new nie rzucał. Teraz rzuca. Wystarczy używać tak:

COS * wsk = new (std::nothrow) COS();

I można sprawdzać z NULLem, czy się alokacja powiodła czy nie.

rzuca wyjątek, którego w sumie zwykle nie ma co łapać, bo skoro jest OOM to program i tak by poszedł w buraki

Według mnie trzeba łapać - a jak masz jakieś cenne dane do zapisu, to co?

Ogolnie rozchodzi sie o to czy ta liczby po usunieciu tabicy nadal tam sa i usuniete jest tylko wskazanie do poczatku obszaru od ktorego sie zaczynaja czy tez nie powinny byc one wykasowane oraz obszar ten powinien zawierac .. wlasnie - co powinien zawierac, NULL ?

delete zwolni pamięć i będzie ona mogła być wykorzystana przez Twój lub inny program ponownie. Ale nie czyści jej. Jeżeli zależy Ci żeby wymazać to co tam masz, to przed kasowaniem ją czyść.

0
Fanael napisał(a)

Co to za sprawdzanie, czy wskaźnik jest nullptrem po new[]?

To jest przeciez zwykłe sprawdzanie czy udalo sie zaalokowac pamiec na tablice 10-cio elementowa typu int.

0

Ogolnie rozchodzi sie o to czy ta liczby po usunieciu tabicy nadal tam sa i usuniete jest tylko wskazanie do poczatku obszaru od ktorego sie zaczynaja czy tez nie powinny byc one wykasowane oraz obszar ten powinien zawierac .. wlasnie - co powinien zawierac, NULL ?

delete zwolni pamięć i będzie ona mogła być wykorzystana przez Twój lub inny program ponownie. Ale nie czyści jej. Jeżeli zależy Ci żeby wymazać to co tam masz, to przed kasowaniem ją czyść.</quote>
Jesli prawda jest to co mowisz, to wlasnie chodzilo mi o taka odpowiedz - 'Nie czyscie pamieci..'.

Mowiąc ze jesli zalezy mi zeby ja wymazac przez wykasowaniem delete / delete [] nalezy ja wyczyścic to masz na mysli np przypisanie zmiennej lub obszaru zmiennych np ZERA ? Czy jest jakis inny sprytny sposob. Thx

0
  1. Zwykłe new i new[] (bez użycia std::nothrow) rzuca wyjątek std::bad_alloc a nie zwraca NULLa
  2. delete i delete[] sprawia że pamięć zostaje oznaczona jako "wolna" (i kolejne alokacje pamięci mogą z niej korzystać), ale nie ingeruje fizycznie w dane znajdujące się w tej pamięci.
  3. Jeśli chcesz skasować to co w tej pamięci leży to musisz to zrobić (choćby ręcznie przypisując nowe wartości) przed użyciem delete lub delete[]
0

Panie -=mAkAbrAs=-, w przypadku OOM pewnie nie będziesz miał jak wykroić kawałka pamięci na pliki czy bufory na te dane.

0

Panie Fanael, chodzi mi np. o sytuację, gdy chce się utworzyć duuużą bitmapę (kilka tys x kilka tys) i niestety nie ma pamięci, więc można użytkownikowi coś wyświetlić. W innych sytuacjach, można pozwalniać wszystko co się zaalokowało i prawidłowo zamknąć program. Więc według mnie jest sens łapać.

0
Fanael napisał(a)

którego w sumie zwykle nie ma co łapać

-=mAkAbrAs=- napisał(a)

W innych sytuacjach, można pozwalniać wszystko co się zaalokowało i prawidłowo zamknąć program.
Czyli w sumie niezłapanie wyjątku też to zrobi - system (nie licząc jakichś przedpotopowych) pozwalnia wszystko, a to całe prawidłowe zamknięcie (czymkolwiek nie jest... Masz na myśli "legalne" wyjście z procesu, tak, jak to się powinno robić? Rantajm przy niezłapanym wyjątku się tym zajmie), też się wykona. Jeśli nie - handler terminate.

-=mAkAbrAs=- napisał(a)

gdy chce się utworzyć duuużą bitmapę (kilka tys x kilka tys) i niestety nie ma pamięci, więc można użytkownikowi coś wyświetlić
Podpada pod "niezwykle" ;)

Ogólnie to zwykle nie ma co się tym przejmować, jak new rzuci to program i tak powinien się wysypać (error można pokazać chociażby handlerem terminate), w prostych programach martwienie się o OOM nie ma większego sensu. W złożonych już lepiej się martwić, ale wtedy to już nie podpada pod "zwykle"... Po co mącić początkującemu? Takie podejście "za każdym rogiem czai się błąd, aby cię zaatakować" jest dobre dla początkujących gangsterów.

0

Po co mącić początkującemu?

Czym skorupka za młodu nasiąknie.. :]

Ale schodzimy na bocznicę, koks zdaje się ma co chciał :)

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