2009-08-20 10 views
5

Załóżmy, że mam wskaźnik przydzielony do przechowywania 4096 bajtów. Jak można zwolnić ostatnie 1024 bajty w C? A co z C++? Co jeśli zamiast tego chciałem zwolnić najpierw 1024 bajtów i zachować resztę (w obu językach)? Co powiesz na dealokację od środka (wydaje mi się, że to wymagałoby podzielenia go na dwa wskaźniki, przed i po rozdzielonym regionie).C i C++: Uwolnienie CZĘŚĆ przydzielonego wskaźnika

+0

Nie jestem tego pewien, ale użycie "fałszywego" wskaźnika o odpowiednim rozmiarze, usunięcie lub uwolnienie tego, którego potrzebujesz, powinno załatwić sprawę, potrzebujesz co najmniej 2 wskaźników. – claf

+1

@ claferri. To jest niezdefiniowane zachowanie. Możesz tylko zwolnić() wskaźniki zwrócone z malloc/realloc - w przeciwnym razie, w jaki sposób free() wie, ile za darmo? – Roddy

+0

@roddy: oups masz rację :) – claf

Odpowiedz

2

Jeśli masz n bajtów malloc przyklejając pamięci, można reallocm bajtów (gdzie m < n), a zatem wyrzucić ostatnie n-m bajtów.

Aby wyrzucić z początku, można malloc nowy, mniejszy bufor i memcpy bajtów, które chcesz, a następnie free oryginał. Ta ostatnia opcja jest również dostępna przy użyciu C++ new i delete. Może również emulować pierwszy przypadek realloc.

+1

"malloc/memcpy/free" to jak realloc może być zaimplementowany wewnętrznie. – Roddy

+1

Zgadzam się, że realloc zazwyczaj zwróci (tę samą) pierwszą część, ale czy jest to oficjalny wymóg ponownego wysłania? Myślę, że tutaj mogą być implementacje, które mogą przenieść dane do nowego miejsca. –

+0

Wyobraź sobie inteligentny schemat realokacji, w którym śledzony jest historyczny wzór alokacji ... jeśli były ostatnio żądania alokacji dla 4096 bajtów, lepiej byłoby przenieść blok kurczący się gdzie indziej, aby zwolnić ten blok 4K. W takim przypadku adres zmieni się. Realloc zwraca wskaźnik do nowego obszaru pamięci, więc programista powinien z niego korzystać. Czy to się zmieni, czy nie. – xcramps

1

Możesz go skrócić za pomocą realloc(). Nie sądzę, żeby reszta była możliwa.

1

Możesz użyć realloc(), aby pozornie zmniejszyć pamięć. Zauważ, że w przypadku niektórych implementacji takie wywołanie faktycznie nie działa. Nie możesz uwolnić pierwszego fragmentu bloku i zachować ostatniego bitu.

Jeśli potrzebujesz tej funkcji, powinieneś rozważyć użycie bardziej złożonej struktury danych. Tablica nie jest właściwą odpowiedzią na każdy problem programistyczny.

+0

Wdrażam system pamięci, więc szukam jak niski poziom dostępu, jak tylko mogę, a jednocześnie pozostać przenośny. – Imagist

1

http://en.wikipedia.org/wiki/New_(C%2B%2B)

STRESZCZENIE: W przeciwieństwie do realloc C za to nie jest możliwe bezpośrednie realokacji pamięci przydzielonej z new []. Aby przedłużyć lub zmniejszyć rozmiar bloku, jeden musi przydzielić nowy blok o odpowiednim rozmiarze , skopiować na starą pamięć, a usunąć stary blok. Biblioteka standardu C++ zapewnia dynamiczną tablicę, w której może zostać rozszerzony lub zmniejszony w swoim szablonie std :: vector o wartości .

12

Nie próbuj odgadnąć zarządzania pamięcią. To zwykle mądrzejszy niż ty ;-)

Jedyną rzeczą, jaką można osiągnąć to pierwszy scenariusz do „zwalnianie” ostatniej 1K

char * foo = malloc(4096); 

foo = realloc(foo, 4096-1024); 

Jednak nawet w tym przypadku, nie ma gwarancji, że „foo "pozostaną niezmienione. Twój cały 4K może zostać zwolniony, a realloc() może przenieść twoją pamięć gdzie indziej, unieważniając w ten sposób wszelkie wskazówki, które możesz posiadać.

Dotyczy to zarówno C i C++ - jednak, korzystanie z malloc() w C++ jest zły zapachy kodu, a większość ludzi będzie oczekiwać na użycie new() przydzielić pamięci masowej. A pamięć przydzielona za pomocą new() nie może być ponownie przydzielona(), a przynajmniej nie w przenośny sposób.Wektory STL byłyby znacznie lepszym podejściem w C++

5

Nie masz "wskaźnika przydzielonego do przechowywania 4096 bajtów", masz wskaźnik do przydzielonego bloku 4096 bajtów.

Jeśli twój blok został przydzielony z malloc(), realloc() pozwoli ci zmniejszyć lub zwiększyć rozmiar bloku. Jednak adres początkowy bloku nie musi być taki sam.

Nie można zmienić adresu początkowego bloku pamięci d, który jest tak naprawdę o to pyta drugi scenariusz. Nie ma również sposobu na podzielenie bloku d z malloc.

To ograniczenie malloc/calloc/realloc/free API - i implementacje mogą polegać na tych ograniczeń (na przykład prowadzenie księgowości informacji o przydziale bezpośrednio przed adresu początkowego, która stałaby przesuwając adres startowy trudny)

teraz malloc nie jest jedynym podzielnik tam. - Twoja platforma lub biblioteki może dostarczyć pozostałych, czy można pisać własne (które pobiera pamięć z systemu poprzez malloc, mmap, VirtualAlloc lub niektóre inny mechanizm), a następnie przekazuje go programowi w dowolny sposób, jaki sobie życzysz.

Dla C++, jeśli przydzielisz pamięć z std::malloc, powyższe informacje dotyczą. Jeśli używasz new i delete, alokujesz pamięć i konstruujesz obiekty, a więc zmiana rozmiaru przydzielonego bloku nie ma sensu - obiekty w C++ mają stały rozmiar.

Powiązane problemy