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

Wskaźniki, czy coś takiego działa poprawnie?

Ostatnio zmodyfikowano 2023-03-24 20:16
Autor Wiadomość
befejak
Temat założony przez niniejszego użytkownika
Wskaźniki, czy coś takiego działa poprawnie?
» 2023-03-24 10:20:13
Witam, ostatnio kombinowałem trochę ze wskaźnikami i zastanawia mnie taki kod:
C/C++
int main() {
   
int * Test;
   
Test = new int[ 50000 ];
   
int * TestDeleter;
   
system( "Pause>nul" );
   
   
TestDeleter = Test;
   
   
delete[ ] TestDeleter;
   
system( "Pause>nul" );
}

Po skompilowaniu i sprawdzeniu w monitorze zasobów wszystko wydaje się działać prawidłowo
 a przynajmniej tak mi się wydaje bo po zwolnieniu tych 50.000 slotów monitor zasobów z 748 kb pokazuje 736 kb w użyciu.
 więc różnica tylko o 12 kb?

Są to wskaźniki więc dla pewności wolę zapytać czy coś takiego czym się bawię jest bezpieczne?

Przy okazji co jeśli bym zrobił:

C/C++
int main() {
   
int * Test;
   
Test = new int[ 50000 ];
   
int * TestOriginal;
   
   
TestOriginal = Test;
   
   
Test = new int[ 50000 ];
}

Czy w takiej sytuacji TestOriginal będzie wielkości 50.000 slotów i będzie posiadać orignalną tablicę od Test
 a Test będzie posiadać nową tablicę o wielkości 50.000 slotów?...

Teraz jak rozumiem delete [] TestOriginal; skasuje tylko te 50.000 slotów na które on wskazuje?
P-180082
DejaVu
» 2023-03-24 15:58:23
Oba kody są poprawne. Dopóki 'nie gubisz' wskaźnika, który trzyma dane wszystko gra.
C/C++
delete[ ] TestOriginal;
Powyższa linijka zwolni pamięć tylko i wyłącznie tego na co wskazuje aktualnie zmienna TestOriginal.
P-180083
pekfos
» 2023-03-24 16:53:28
Wskaźnik to jest po prostu liczba - adres w pamięci. Jeśli każdy adres uzyskany z new/new[]/malloc()/itp trafi kiedyś, dokładnie raz i do odpowiedniego  delete/delete[]/free()/itp, to jest poprawnie. Nieważne co się będzie działo po drodze z tymi wskaźnikami.

czy coś takiego czym się bawię jest bezpieczne?
Jeśli potrzebujesz pytać, to nie jest bezpieczne. Praktyka pokazuje że większość programistów nie umie używać wskaźników poprawnie, a mimo to pisze w C++ kod w stylu C, przez co C++ ma reputację jednego z tych "niebezpiecznych języków". Pisz w C++ w C++ i używaj kontenerów, a ręcznej alokacji i dealokacji kiedy musisz, czyli prawie nigdy. Kiedy już nastąpi ten moment, to upewnij się że niezależnie od ścieżki wykonania (wliczając w to wyjątki) pamięć jest poprawnie zwolniona i nie jest używana po zwolnieniu.
P-180084
befejak
Temat założony przez niniejszego użytkownika
» 2023-03-24 19:46:09
Czyli niezależnie jaki wskaźnik rejestruje pamięć, tak długo jak mam adress tej pamięci gdziekolwiek
 i użyję właściwego delete na właściwym adresie to wskaźniki mogą się dowolnie wymieniać adresami.


Pozwolę sobie jeszcze zadać pytanie, skąd delete[]; wie jak dużo zwolnić pamięci?
 Jest jakaś opcja aby znaleźć pamięć jak napisał DejaVu, która "zgubi" się?


@Pekfos, czytałem o tym artykuł i dlatego zawsze jak używam wskaźników to pierwszą rzeczą którą
 robię jest zawsze utworzenie delete dla takiego wskaźnika.

Na końcu funkcji albo w destruktorze, albo czasem od razu piszę void FreeMemory(); ( jeśli ma "żyć" inną długość czasu )

Jedna z funkcji z programu "Notatnik od zaplecza" o który już kilka razy pytałem,
 Naczytałem się wystarczająco że nawet posiadam zmienną ( bool ) Exist aby upewnić się że pamięć istnieje.
 Bo jak czytałem kiedyś artykuł wywołanie delete[] na wskaźniku który na nic nie wskazuje jest również złe
 ( chociaż w tym artykule nie powiedzieli dlaczego? )
C/C++
void qDelete() {
   
if( !Exist ) {
       
return; }
   
Exist = false;
   
Length = 0;
   
delete[ ] Char;
   
return;
}
Funkcja upewnia się że pamięć istnieje, ustawia Exist na false ( aby nie wywołać funkcji ponownie )
 Ustawia Length na 0 ( aby żadne processy nie starały się odczytać wartości w tablicy )

I na końcu finalnie kasuje pamięć, upewniając się wcześniej że wszystko powinno być ok :)

//Edit: poprawka literówki.
P-180085
pekfos
» 2023-03-24 20:16:03
Pozwolę sobie jeszcze zadać pytanie, skąd delete[]; wie jak dużo zwolnić pamięci?
Typowa implementacja alokuje więcej pamięci żeby przechować też swoje rzeczy.

 Jest jakaś opcja aby znaleźć pamięć jak napisał DejaVu, która "zgubi" się?
Są na to narzędzia typu valgrind, heaptrack, etc.

@Pekfos, czytałem o tym artykuł i dlatego zawsze jak używam wskaźników to pierwszą rzeczą którą
 robię jest zawsze utworzenie delete dla takiego wskaźnika.
Brzmi jakby ten artykuł wyrządził więcej szkody niż pożytku. To tak jak uczyć ludzi żeby nigdy nie cięli do siebie nożem. Może i tego nie będą robić, co nie znaczy że przypadkiem nie pchną kogoś obok, prawda? Trzeba rozumieć problemy i zagrożenia, a nie "stawiać delete". Ile tych delete stawiasz? Jedno na start, a potem jak pojawia się inna ścieżka wykonania to pamiętasz o zwalnianiu wszystkiego? Bierzesz pod uwagę ścieżki wykonania przy propagacji wyjątków? Core guidelines daje lepszą radę niż delete: Immediately give the result of an explicit resource allocation to a manager object.

 Naczytałem się wystarczająco że nawet posiadam zmienną ( bool ) Exist aby upewnić się że pamięć istnieje.
 Bo jak czytałem kiedyś artykuł wywołanie delete[] na wskaźniku który na nic nie wskazuje jest również złe
 ( chociaż w tym artykule nie powiedzieli dlaczego? )
delete ma dobrze zdefiniowane zachowanie dla pustego wskaźnika. Nawet gdyby nie, możesz sprawdzać wartość samego wskaźnika zamiast dodawać nową zmienną.
P-180086
« 1 »
  Strona 1 z 1