b00rt00s Temat założony przez niniejszego użytkownika |
[c++] problemy ze zwalnianiem pamieci (memcpy, free, delete) » 2013-10-22 06:14:54 Od razu podam, ze słaby jestem w te klocki, więc proszę o cierpliwość. Chcę napisać, który program otrzyma dane w postaci wypełnionego obszaru pamięci o wskaźniku char* i znanym rozmiarze. Wiadomo, że obszar zajmowany jest całkowicie przez obiekt znanej klasy. Teraz muszę przerobić ten obszar pamięci na normalny obiekt klasy. Żeby sobie przetrenować takie operacje, napisałem prosty program testowy: #include <iostream> #include <cstring>
using namespace std;
int main() { string tekst1( "jakis tekst" ); char * zrodlo =( char * )( & tekst1 ); size_t rozmiar = tekst1.length(); char * bufor = new char[ rozmiar ]; string * tekst2 = new( bufor ) string(); memcpy( tekst2, zrodlo, rozmiar ); cout <<* tekst2 << endl; free( tekst2 ); return 0; } Moje pytanie brzmi: dlaczego wykonanie operatora delete kończy się crashem? Albo inaczej, jak uzyskać poprawny wskaźnik na typ string, którym można manipulować jak każdym innym wskaźnikiem? P.S. Docelowo docelowa klasa ma być zupełnie inna, jednak próbuje zrozumieć mechanizm. |
|
Mrovqa |
» 2013-10-22 07:31:36 1. Jeżeli coś alokujesz operatorem new to możesz to dealokować tylko i wyłącznie operatorem delete. Podobnie - dla malloc wykorzystuje się free. 2. Ty wiesz co to jest std::string? To jest klasa, a nie tablica znaków. W ten sposób nie pobierzesz wskaźnika char*. Masz dwie możliwości: string * zrodlo = & tekst1; char * zrodlo2 = & tekst1[ 0 ];
|
|
b00rt00s Temat założony przez niniejszego użytkownika |
» 2013-10-22 09:33:40 Chyba źle zostałem zrozumiany. W tym przypadku użyłem std::string jako przykładu. Docelowo chodzi mi o to, że mogę dostawać obiekty w postaci obszaru pamięci. Ten obszar może być zapisany jako tablica typu char. Teraz mi chodzi o to, jak ten obszar przekonwertować na wskaźnik na obiekt klasy. Klasa obiektu jest oczywiście określona.
[EDIT]
Cholera, wiem co zrobiłem nie tak... Wywołując memcpy wykonałem kopię stringa, ale bez głębokiego kopiowania, a wewnątrz stringa jest przecież wskaźnik (tablica) typu char. Wykonując operator delete wykonuję destruktor klasy, który usuwa tą tablicę. Sęk w tym, że ona będzie usunięta automatycznie, bo pierwszy string był na stosie i mam podwójne zwolnienie pamięci... Używając free nie wywołuję destruktora i dlatego nie ma błędu... |
|
pekfos |
» 2013-10-22 09:43:22 length() nie zwraca rozmiaru obiektu stringa. Poza tym nie można mieszać malloc() i free() z new i delete. Wykonując operator delete |
Nie można wywoływać delete, dla obiektów utworzonych przez placement new. PS: Prawdę mówiąc, w tym kodzie nie ma niczego poprawnego, jeśli chodzi o obsługę dynamicznej pamięci. Poczytaj najpierw, jak się tego używa i nie mówię tylko o placement new. |
|
b00rt00s Temat założony przez niniejszego użytkownika |
» 2013-10-22 19:57:41 PS: Prawdę mówiąc, w tym kodzie nie ma niczego poprawnego, jeśli chodzi o obsługę dynamicznej pamięci. |
Widzę, że cały czas nie zostałem zrozumiany. Linie: char * zrodlo =( char * )( & tekst1 ); size_t rozmiar = tekst1.length(); to coś na co nie mam wpływu! Tak właśnie dostanę obiekt: jako wypełniony obszar pamięci. Teraz moim zadaniem jest przekształcić ten obszar na wskaźnik do konkretnej klasy. Poeksperymentowałem trochę i doszedłem do rozwiązania problemu: #include <iostream> #include <cstring>
using namespace std;
int main() { string tekst1( "jakis tekst" ); char * zrodlo =( char * )( & tekst1 ); string * tekst2 =( string * ) zrodlo; string * tekst3 = new string( * tekst2 ); cout <<* tekst3 << endl; delete tekst3; return 0; }
Mój problem polegał na tym, że należało poprawnie skopiować obiekt z obszaru pamięci do nowej zmiennej. Zamiast memcpy wykonałem rzutowanie wskaźnika, a następnie wykorzystałem konstruktor kopiujący, który wykonał głębokie kopiowanie. Po przeanalizowaniu kodu valigrindem okazało się, że nie było żądnych wycieków pamięci. Temat chyba do zamknięcia... |
|
« 1 » |