Wie auf null raus, neuen Speicher nach realloc
Was ist der beste Weg, um null aus neue Speicher nach dem Aufruf von realloc, während der ursprünglich zugewiesenen Speicher intakt?
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
size_t COLORCOUNT = 4;
typedef struct rgb_t {
int r;
int g;
int b;
} rgb_t;
rgb_t** colors;
void addColor(size_t i, int r, int g, int b) {
rgb_t* color;
if (i >= COLORCOUNT) {
//new memory wont be NULL
colors = realloc(colors, sizeof(rgb_t*) * i);
//something messy like this...
//memset(colors[COLORCOUNT-1],0 ,sizeof(rgb_t*) * (i - COLORCOUNT - 1));
//...or just do this (EDIT)
for (j=COLORCOUNT; j<i; j++) {
colors[j] = NULL;
}
COLORCOUNT = i;
}
color = malloc(sizeof(rgb_t));
color->r = r;
color->g = g;
color->b = b;
colors[i] = color;
}
void freeColors() {
size_t i;
for (i=0; i<COLORCOUNT; i++) {
printf("%x\n", colors[i]);
//can't do this if memory isn't NULL
//if (colors[i])
// free(colors[i]);
}
}
int main() {
colors = malloc(sizeof(rgb_t*) * COLORCOUNT);
memset(colors,0,sizeof(rgb_t*) * COLORCOUNT);
addColor(0, 255, 0, 0);
addColor(3, 255, 255, 0);
addColor(7, 0, 255, 0);
freeColors();
getchar();
}
- Dies hat eine sehr schlechte Leistung, wenn man die Farbe wird Hinzugefügt, um das Ende der Liste der Farben, die übliche Aufruf-Muster. Sie werde nur hinzufügen, ein element in einer Zeit, bevor die Neuzuweisung. Betrachten Sie mindestens Zuweisung max(i+1, COLORCOUNT * 2).
- Dies ist nur ein Beispiel um das problem zu veranschaulichen. Die eigentliche Quelle ist eine hash-Tabelle, die die Größe von Primzahl IIRC
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es wahrscheinlich keine Notwendigkeit zu tun, die
memset
: Sie können nicht mitcolors[k]
bevor Sie es mit etwas gültiges später. Zum Beispiel, dein code setztcolors[i]
zu einer neu zugeteiltencolor
Zeiger, so dass Sie nicht brauchen, um setcolors[i]
zuNULL
.Aber, selbst wenn Sie wollten "null heraus, so ist alles schön", oder wirklich brauchen, die neuen Zeiger zu
NULL
: der C-standard garantiert nicht, dass alle bits null wird der null-Zeiger-Konstante (d.h.,NULL
), somemset()
ist nicht die richtige Lösung sowieso.Nur tragbare Sache, die Sie tun können, ist, um jede Zeiger auf
NULL
in einer Schleife:Ihre primäre problem ist, dass Ihr
realloc()
nennen, ist falsch.realloc()
gibt einen Zeiger auf den Speicher in der Größe verändert, ist es nicht (unbedingt) die Größe in-place.So, das sollten Sie tun:
Wenn Sie wirklich wollen, zu wissen, was die
memset()
nennen sollte, die Sie benötigen, um die Einstellung auf null die Speicher abcolors+COLORCOUNT
, und legen Siei+1-COLORCOUNT
Mitglieder zu null:Aber wie ich oben sagte, alle bytes null ist nicht garantiert, dass ein
NULL
Zeiger, also Ihrememset()
sowieso schon sinnlos ist. Sie müssen eine Schleife verwenden, wenn Sie möchtenNULL
Zeiger.assert(NULL == 0)
am Anfang des Programms als schreiben eine Tonne von komplexen und bizarren code zu unterstützen, dass eine zufällige Umsetzung, wählt etwas anderes.Gibt es keine Möglichkeit, dies zu lösen, als ein Allgemeines Muster. Der Grund warum ist, dass, um zu wissen, was Teil des Puffers ist neues Sie müssen wissen, wie lange die alten Puffer wurde. Es ist nicht möglich zu bestimmen, diese in C und damit verhindert, dass eine Allgemeine Lösung.
Aber könnten Sie schreiben eine wrapper-wie so
Zunächst realloc kann fehlschlagen, so dass du auf NULL prüfen muss. Zweitens, es gibt keinen besseren Weg, um null aus der Erinnerung: gerade memset vom Ende des alten Puffer an das Ende der größeren Puffer.
Deine eigene Funktion schreiben, sagen
reallocz
, akzeptiert die aktuelle Größe als parameter, und fordertrealloc
undmemset
für Sie. Es ist wirklich nicht viel besser als das, was Sie bereits haben... es ist C, nachdem alle.