Frage zu Speicherverwaltung

20/05/2009 - 13:53 von Christian Seifert | Report spam
Hallo,

ich habe mir einen kleinen Header geschrieben welche mir den NULL-
check nach malloc/realloc/calloc abnimmt und zudem beim free den
Pointer auch NULL setzt. Funktioniert soweit super. Jetzt habe ich mir
noch gedacht das ich mir ein paar Infos mit speichere wenn ich
irgendwo Speicher allokiere um ggf. am Ende des Programms
festzustellen das ich vllt. doch irgendwo ein free vergessen habe.
Also habe ich mir eine Struktur erstellt in der ich den allokierten
Block mitspeichere und zusàtzlich Infos zur Datei und zur Zeile wo
allokiert wird. Von dieser Struktur ein 2-Dimensionals Array (table)
gemacht und einfach mal mit gespeichert. Funktioniert erstmal alles
soweit ganz gut.

=8<static inline void
_add_mem_info(void* p,
char const* filename,
size_t linenum)
{
if (_g_is_init == 0)
safe_memory_init();

_mem_info_table = realloc(_mem_info_table,
sizeof(mem_info) * (_g_counter + 1));
_mem_info_table[_g_counter] = malloc(sizeof(mem_info));
_mem_info_table[_g_counter]->block_start = p;
size_t len = strlen(filename);
_mem_info_table[_g_counter]->filename = malloc(len + 1);
strncpy(_mem_info_table[_g_counter]->filename, filename, len);
_mem_info_table[_g_counter]->filename[len] = '\0';
_mem_info_table[_g_counter]->linenum = linenum;
}
=>8
Ich habe allerdings ein Problem wenn ich bspw. 2 Blöcke allokiere, den
ersten Pointer mit free freigebe und den 2. sozusagen "vergesse". In
meiner free-Funktion wo ich free aufrufe und den Pointer auf NULL
setze entferne ich natürlich wieder die gespeicherten Infos aus meiner
table.

=8<static inline void
_remove_mem_info(void* p)
{
unsigned int i;
for (i = 0; i < _g_counter; ++i)
{
if (_mem_info_table[i]->block_start == p && i != (_g_counter - 1))
{
memmove(_mem_info_table[i]->block_start + i,
_mem_info_table[i]->block_start + i + 1,
sizeof(void*) * (_g_counter - i - 1));

free(_mem_info_table[i]->block_start);
_mem_info_table[i]->block_start = NULL;
free(_mem_info_table[i]->filename);
_mem_info_table[i]->filename = NULL;
free(_mem_info_table[i]);
_mem_info_table[i] = NULL;
}
}
}
=>8
Jetzt wird beim Programmende die restlichen, noch nicht freigegebenen
Speicher, freigegeben. Jetzt ist allerdings das Problem das ich dann
ein "Invalid free()" von valgrind bekomme. Problem ist das es trotz
entfernen aus der table anscheinend versucht den schon frei gegebenen
Speicher noch einmal frei gegeben wird und der noch nicht freigegebene
Speicher bleibt allokiert und wird auch nicht freigegeben wo valgrind
natürlich auch was dagegen hat. Wenn ich aber den zuletzt allokierten
Pointer freigebe und den 1. dafür "vergesse" gibt es keine Probleme.
Meine Frage: Wenn ich mit memove den freigegeben Speicher mit anderem
überschreibe, da ich ihn aus meiner table entfernt habe, wird da auch
die Adresse mitverschoben oder eben nicht und es deshalb zu dem
"invalid free()" kommt?

Falls der komplette Code benötigt wird findet Ihr den hier:
http://pastebin.com/m34686d4a

Mein kurzes Testprogramm:
=8<#include "safe_memory.h"

int main(int argc, char* argv[]) {
int* p, *bad;
p = safe_malloc(sizeof(int));
bad = safe_malloc(sizeof(int));
printf("address of p in main: %p", p);
printf("address of bad in main: %p", bad);
safe_free(bad); // wenn ich hier statt bad, p einsetze kommt es zu
dem "invalid free()"
return 0;
}
=>8
Hoffe man kann mir noch helfen :D

Grüße
Christian

P.S.: Wer weiß wie ich noch "still reachable" die mir ebenfalls
valgrind meldet wegbekomme wàre super, aber laut valgrind-Docu ist das
nichts schlimmes sondern wàre nur Fleißarbeit vom Entwickler :)
 

Lesen sie die antworten

#1 Alexander Bartolich
21/05/2009 - 19:23 | Warnen spam
Christian Seifert schrieb:
[...]
Hoffe man kann mir noch helfen :D



In _add_mem_info fehlt "_g_counter++"
In _remove_mem_info darfst du memmove erst nach dem free machen.

seq 100 | sed 's/.*/Romani Ite Domum./'

Ähnliche fragen