Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Operatory new oraz delete.

Ostatnio zmodyfikowano 2016-04-18 14:50
Autor Wiadomość
Knayder
Temat założony przez niniejszego użytkownika
Operatory new oraz delete.
» 2016-04-18 07:27:44
Witam, czytając o wskaźnikach w książce Symfonia C++, natrafiłem na wspomniane w temacie operatory. Spodobał mi się ich sposób działania, jednak po przetestowaniu ich, nie uzyskałem satysfakcjonującego mnie wyniku. Napisałem prosty program, który nie powinien się skompilować, a jednak. Czy byłby ktoś tak miły i wytłumaczył mi, dlaczego to "działa"?
C/C++
#include <iostream>

using namespace std;


int main()
{
    int * a;
    a = new int( 32 );
    cout << "Poczatkowe a: " << * a << endl;
    cout << "Usuwam a" << endl;
    delete a;
    cout << "a po usunieciu: " << * a << endl; //Tutaj *a juz nie powinno istniec, a jednak
    * a += 12;
    cout << "a po dodaniu: " << * a << endl;
    return 0;
}
OUTPUT
Poczatkowe a: 32
Usuwam a
a po usunieciu: 32
a po dodaniu: 44
P-147373
pekfos
» 2016-04-18 08:35:32
To przypadek, że działa.

który nie powinien się skompilować, a jednak.
Nie ma powodów, żeby to się nie skompilowało. Kompilator nie wyłapie błędów w działaniu programu i nawet specjalnie nie próbuje.
P-147376
carlosmay
» 2016-04-18 08:37:40
C/C++
//Tutaj *a juz nie powinno istniec, a jednak
Fizycznie wskaźnik o nazwie 'a' nie jest usuwany, tylko zwolniona jest pamięć, na którą wskazywał.
Wszystkie operacje za pośrednictwem tego wskaźnika są możliwe, jednak jest niezdefiniowane zachowanie, więc wyniki mogą być różne.

Dla bezpieczeństwa należy po zwolnieniu pamięci "wyzerować" wskaźnik.
a = nullptr;
P-147377
j23
» 2016-04-18 11:45:03
@carlosmay, OP nie pytał o wskaźnik, tylko o pamięć na którą ten wskaźnik wskazuje.

@Knayder, To działa, ponieważ delete nie usuwa pamięci, a jedynie ją zwalnia. Jeśli zwolniona pamięć leży na tej samej stronie pamięci co inne alokacje (w użyciu), wtedy taka pamięć będzie cały czas dostępna i nie wywoła błędu AV. W momencie, gdy zwalniana pamięć jest ostatnią używaną pamięcią na stronie, wtedy sterta może zwolnić i odmapować całą stronę, a wtedy próba dostępu spowoduje błąd AV.


P-147378
michal11
» 2016-04-18 11:56:57
@Knayder a co właściwie twoim zdaniem powinno się zdarzyć po usunięciu *a ?
P-147379
carlosmay
» 2016-04-18 12:31:36
Jeśli zwolniona pamięć leży na tej samej stronie pamięci co inne alokacje (w użyciu), wtedy taka pamięć będzie cały czas dostępna i nie wywoła błędu AV.
Czy takie zachowanie jest standardem czy jest niezdefiniowane?
P-147380
Knayder
Temat założony przez niniejszego użytkownika
» 2016-04-18 12:54:00
Ja sobie wyobrażałem w taki sposób, że po wywołaniu delete na wskaźniku a, obiekt na który wskazuje, zostanie usunięty i wtedy próba wypisania tego na co wskazuje byłaby równoznaczna z czymś takim:
cout << niezdefiniowana_zmienna << endl;
P-147382
j23
» 2016-04-18 14:15:40
@carlosmay, wszystko zależy od tego, jak zaimplementowana jest sterta, no i generalnie jak wygląda zarządzanie pamięcią w systemie.

@Knayder, niezdefiniowana zmienna powoduje błąd kompilacji, a my tu mówimy o sytuacji w czasie wykonania. Wywołanie delete powoduje, że pamięć zostaje zwolniona, a aplikacja nie powinna się do niej odwoływać, niezależnie od tego, czy fizycznie ona gdzieś tam jeszcze jest czy nie. Koniec, kropka.
P-147385
« 1 » 2
  Strona 1 z 2 Następna strona