realloc verliert Daten?
-
Hallo Forum,
ich arbeite mich gerade in C ein und habe ein Problem mit realloc. Die vorhandenen Daten gehen verloren. Ich habe ein struct. In einer init-Funktion hole ich mir den Speicher für 32 * Größe des Structs. Das klappt auch alles wunderbar. In einer anderen Funktion durchlaufe ich die Elemnte solange bis ich auf eines treffe, in dem ein Flag 0 ist. In diesem Fall verlasse ich die Schleife mit break. Dann kommen ein paar Aktionen auf dieses Element und dann kommt realloc.
int foo(struct bar *clnt, int *size) { struct bar new_clnt; for (i=0; i < *size; i++) { c_clnt = &clnt[i]; if (c_clnt->id != 0) continue; break; } {...} if ((i + 3) > *size) { new_clnt = (struct abc*)realloc((clnt, *size + INIT_CLNT) * sizeof(struct abc)); if (new_clnt == 0) return -1; *size += INIT_CLNT; } clnt = new_clnt; return 0; }
Im Grundegenommen funktioniert das auch, aber sind nachdem realloc alle Daten weg. Das ID aus Element 0 hat dann nicht mehr den Wert 1 (der war vorher drin) sondern 1628570492 und Elemnet 1 (hatte den Wert 2) hat dann 0. In dieser malloc man page habe ich (wenn ich es richtig verstanden habe) gelesen, das realloc die bestehenden Daten nicht verändert, aber tut er es doch? Oder ist mein Code falsch? Wenn realloc die Daten wirklich verändert bzw. einen ganz neuen Bereich allokiert und die Daten nicht kopiert, wer ist dran Schuld? Der Compiler? Das OS?
Wäre schön wenn mir jemand dazu was sagen könnte.
Gruß, TIA
-Funny-
PS: Als "Newbie" bin ich gerne für jeden Verbesserungsvorschlag an meinem Code offen
-
int foo(struct bar *clnt, int *size);
ist auf jeden Fall falsch deklariert. realloc verändert die Anzahl der reservierten Bytes. Die Adresse, auf die clnt zeigt, muss nicht mit der von der Ausgabe von realloc übereinstimmen. Du solltest deshalb einen Zeiger auf deinen Zeiger benutzen, also
int foo(struct bar **clnt, int *size);
Ich würde auch ein Paar Änderungen machen, wie:
int foo(struct bar **clnt, int *size) { struct bar *new_clnt; /* Als Pointer! */ struct bar *tmp=*clnt; for (i=0; i < *size; i++) { if (tmp[i].id != 0) continue; break; } {...} if ((i + 3) > *size) { new_clnt = realloc(tmp, (*size + INIT_CLNT) * sizeof(struct bar)); if (new_clnt == 0) return -1; *size += INIT_CLNT; tmp = new_clnt; *clnt = tmp; } /* tmp = new_clnt; *clnt = tmp; */ /* nicht unbedingt hier stellen !*/ return 0; } void foo_bar() { strcut map *irgendwas; int* wieviel; ... foo(&irgendwas, wieviel); /* so musst du es aufrufen */ }
-
So,
ich habe mal versucht deine Änderungen einzubauen, aber immernoch den gleichen Effekt. Ich kopiere mal den kompletten Code der Funktion, vielleicht findet jemand noch einen Fehler (und bestimmt noch ein paar Verberssungsvorschläge).
int add_client(int s, struct chat_client **clnt, int *size_clnt, struct chat_cookie *ck) { int i; struct chat_client *new_clnt; struct chat_client *tmp=*clnt; time_t t; char welcome[] = "Willkommen im Chat<br><br>"; printf("In add_client(), size of client struct is %i\n", *size_clnt); time(&t); /* Search next free element */ for (i = 0; i < *size_clnt; i++) { printf("Such bei ID %i: %i\n", i, tmp[i].id); if (tmp[i].id != 0) continue; tmp[i].id = i + 1; tmp[i].socket_id = s; strcpy(tmp[i].cookie.cookie, ck->cookie); strcpy(tmp[i].cookie.nick, ck->nick); tmp[i].cookie.c_time = ck->c_time; tmp[i].keep_alive = t; break; } /* Reached we the last element? */ if (i > MAX_CLIENTS) return -1; /* We need code the resize the clients array if there are less than 3 free elements. */ if ((i + 3) > *size_clnt) { new_clnt = (struct chat_client*)realloc(tmp, (*size_clnt + INIT_CLIENTS) * sizeof(struct chat_client)); if (new_clnt == 0) return -1; *size_clnt += INIT_CLIENTS; tmp = new_clnt; *clnt = tmp; } write(s, welcome, strlen(welcome)); return i; }
Aufgerufen wird die Funktion mit
clnt_id = add_client(c, &clnt, size_clnt, &c_lst[ck_id]);
c ist das Ergebnis eines socket_accept, clnt ist das besagte struct "chat client", size_clnt ist ein Pointer auf ein INT und c_lst ist ein Array eines anderen structs.
Beim 29. Aufruf von add_client() gibt es folgende Ausgabe
In add_client(), size of client struct is 32
Such bei ID 0: 1
Such bei ID 1: 2
Such bei ID 2: 3
Such bei ID 3: 4
Such bei ID 4: 5
Such bei ID 5: 6
Such bei ID 6: 7
Such bei ID 7: 8
Such bei ID 8: 9
Such bei ID 9: 10
Such bei ID 10: 11
Such bei ID 11: 12
Such bei ID 12: 13
Such bei ID 13: 14
Such bei ID 14: 15
Such bei ID 15: 16
Such bei ID 16: 17
Such bei ID 17: 18
Such bei ID 18: 19
Such bei ID 19: 20
Such bei ID 20: 21
Such bei ID 21: 22
Such bei ID 22: 23
Such bei ID 23: 24
Such bei ID 24: 25
Such bei ID 25: 26
Such bei ID 26: 27
Such bei ID 27: 28
Such bei ID 28: 29
Such bei ID 29: 30
Such bei ID 30: 0Beim 30. Aufruf kommt dann
In add_client(), size of client struct is 64
Such bei ID 0: 1
Such bei ID 1: 1628570492Vielleicht ist ja folgender Hinweis nützlich: Ich arbeite unter cygwin mit "gcc 3.3.3 (cygwin special)".