Forum: PC-Programmierung Probleme mit dynamischem 2dimensionalem Array in C


von Array (Gast)


Lesenswert?

Hallo!

Ich habe schon wieder in kleines Problem. Ausgangspunkt stellt diese 
Page dar:
http://pronix.linuxdelta.de/C/standard_C/c_programmierung_17_1.shtml#8
Dort wird sehr schön erklärt wie man dynamisch 2 dimensionale Arrays 
erstellt. Ich habe ihn auch so weit verstanden (glaube ich zumindest, 
diese Pointer auf Pointer geschichte ist schon 
Hirnschmalzbeanspruchend). Ich möchte diesen Code aber nicht einfach so 
verwenden, sondern ihn in einzelne Funktionen unterteilen, damit ich in 
einem Programm diese verwenden kann. Dies funktioniert allerdings nicht.
Ich gehe davon aus, dass es ein ähnliches Problem ist wie bei der 
klassischen swap-funktion: werden nicht pointer auf die Variablen 
übergeben ist nach beenden der Funktion nicht vertauscht. Ich hoffe ihr 
wisst was ich meine...
Auf jeden Fall habe ich eine Funktion gebastelt, die eigentlich 
lediglich ein paar neue Zeiger auf Zeiger erstellen soll (eigentlich ist 
es (bis auf die Namensgebung) aus dem Beispielprogramm geraubt:
1
int new_zeilen(int n, int **matrix){
2
  /* reserviert den Speicher für n neue zeilen-zeiger */
3
   matrix = (int **)malloc(n*sizeof(int *));
4
   if(matrix == NULL) return 1;
5
   return 0;
6
}

Hier funktioniert der Code auch noch, aber wenn danach eine Spalte 
erzeugt werden soll, dann gibt es einen Fehler der darauf hindeuten 
lässt, dass im vorhergehenden Schritt (in meiner Funktion) was schief 
gegangen ist.

Unhandled exception at 0x00412085 in DynMem.exe: 0xC0000005: Access 
violation writing location 0x00000000.

Ich hoffe jemand kann mir helfen...

von yalu (Gast)


Lesenswert?

> Hier funktioniert der Code auch noch, aber wenn danach eine Spalte
> erzeugt werden soll, dann gibt es einen Fehler der darauf hindeuten
> lässt, dass im vorhergehenden Schritt (in meiner Funktion) was
> schief gegangen ist.

Wieso deutet die Fehlermeldung darauf hin, dass der Fehler in der
geposteten Funktion liegt? Ich sehe da keinen Zusammenhang. Warum
postest du den Spaltenteil nicht ebenfalls?

Was mir allerdings auffällt: Was passiert mit dem Parameter Matrix? Er
wird nicht benutzt, sondern einfach überschrieben. Der neue Wert wird
ebenfalls nicht genutzt. Wolltest du über den Parameter matrix einen
Pointer an den Aufrufer zurückgeben? Wenn ja, sollte das eher so
aussehen:
1
int new_zeilen(int n, int ***matrix){
2
  /* reserviert den Speicher für n neue zeilen-zeiger */
3
   *matrix = (int **)malloc(n*sizeof(int *));
4
   if(*matrix == NULL) return 1;
5
   return 0;
6
}

(Man beachte die drei zusätzlichen Sterne.)

von Array (Gast)


Lesenswert?

Hallo!

Vielen Dank für deine Hilfe, mit der Änderung komme ich immerhin schon 
einen Schritt weiter. Da es aber schwierig zum beschreiben ist, wie ich 
wo was meine, habe ich in Minimalprogramm geschrieben, das eigentlich 
alle funktionalität enthält, aber die Fehlerquellen zeigen kann so dass 
ich evtl daran weiter arbeiten kann.
Hier der Code:
1
#include "stdlib.h"
2
3
4
int nr_of_packets(int **buffer){
5
  /* Gibt die Anzahl allozierte Speicherplätze für Paket-Pointer zurück */
6
  int i = 0;
7
  if(buffer == NULL) return 0;
8
  while(buffer[i++] != NULL);
9
  return i;
10
}
11
12
int save_new_packet(int packet_number, int *packet, int packet_size, int ***buffer){
13
  /* reserviert, falls nötig neue Speicherplätze für Paket-Pointer, und speicher die Daten in packet ab*/
14
  int new_packet_pointers = packet_number - nr_of_packets(*buffer);
15
  if(new_packet_pointers > 0){
16
    *buffer = (int **)realloc(**buffer, new_packet_pointers*sizeof(int *)); // <--
17
    if(*buffer == NULL) return 1;
18
  }
19
   
20
   /* Allozieren des Speichern für das Paket */
21
   *buffer[packet_number] = (int *)malloc(packet_size*sizeof(int));
22
   if(*buffer[packet_number] == NULL) return 2;
23
   /* Speichern der Daten */
24
   for(; packet_size > 0; packet_size--){
25
     *buffer[packet_number][packet_size] = *(packet + packet_size);
26
   }
27
   return 0;
28
}
29
30
int main(){
31
   int **buffer = NULL;
32
   int packet[5]={4,6,7,8,3};
33
   save_new_packet(1, packet, 5, &buffer);
34
}

Der fehler der Accessviolation tritt an der Stelle, die mit <-- markiert 
ist auf. Ich hoffe es wird einigermassen klar was das Ding tun soll.
Eigentlich habe ich das Ding mit den Pointern schon verstanden, aber bei 
2 Dimensionalen Geschichten wirds einfach nochmals eine Stufe 
schwieriger und dann noch das ganze als Pointer übergeben... Also bei 
*** wirds dann nicht mehr sehr anschaulich. Wenn mir jemand helfen kann, 
DANKE!

Mfg

von Jorge (Gast)


Lesenswert?

realloc macht man nicht! Nimm free und alloc.

von COMPILIERENli (Gast)


Lesenswert?

Hallo!

Auch wenn das das eigentliche Problem nicht löst: Danke. Weshalb sollte 
ich realloc nicht nehmen? Wenn ichs mit (m)alloc und free löse, dann 
muss ich den ganzen Inhalt zuerst zwischen speichern, das ist dann aber 
ziemlich speicherintensiv...

von Jorge (Gast)


Lesenswert?

Die Funktion von realloc ist nicht überall gleich. Manchaml wird so 
verfahren, dass der Speicher nur verkleinert werden kann.

Speicheroperationen free und alloc sind meist sehr effizient. Ein 
Engpass entsteht nur in unglücklichen Situationen wenn die 
Fragmentierung zum Tragen kommt. In Sprachen wie Java oder Lisp gibt es 
dafür die GC=Garbage Collection.

--> **buffer in realloc ist NULL soweit ich das jetzt überblicke

von Karl H. (kbuchegg)


Lesenswert?

Warum hier
1
    *buffer = (int **)realloc(**buffer, new_packet_pointers*sizeof(int *)); // <--
dem realloc den **buffer vorwerfen?
realloc möchte einfach nur die Speicheradresse, an der sich der
Speicher momentan befindet. Das wäre in deinem Fall *buffer
1
    *buffer = (int **)realloc(*buffer, new_packet_pointers*sizeof(int *)); // <--

PS: Vergiss die Aussage, das man realloc nicht macht. realloc
ist perfekt für C und ganz im Gegenteil, wenn man dynamische
Strukturen hat benutzt man realloc aus Performancegründen, da
einem ein realloc unter Umständen das Umkopieren von Daten
ersparen kann.

> Die Funktion von realloc ist nicht überall gleich.
Unsinn. realloc ist eine Standard-C Funktion. Wenn die nicht
überall gleich funktioniert, dann ist die betreffende Library
fehlerhaft und sollte ausgetauscht werden.

von Karl H. (kbuchegg)


Lesenswert?

> aber bei
> 2 Dimensionalen Geschichten wirds einfach nochmals eine Stufe
> schwieriger und dann noch das ganze als Pointer übergeben... Also bei
> *** wirds dann nicht mehr sehr anschaulich.

Dann definier dir einen typedef für einen 2-fach Pointer und arbeite
damit weiter
1
typedef int ArrayType;
2
typedef ArrayType*  Array_1;
3
typedef Array_1* Array_2;
4
5
int nr_of_packets(Array_2 buffer){
6
  /* Gibt die Anzahl allozierte Speicherplätze für Paket-Pointer zurück */
7
  int i = 0;
8
  if(buffer == NULL) return 0;
9
  while(buffer[i++] != NULL);
10
  return i;
11
}
12
13
int save_new_packet(int packet_number, int *packet, int packet_size, Array_2 *buffer){
14
  /* reserviert, falls nötig neue Speicherplätze für Paket-Pointer, und speicher die Daten in packet ab*/
15
  int new_packet_pointers = packet_number - nr_of_packets(*buffer);
16
  if(new_packet_pointers > 0){
17
    *buffer = realloc(*buffer, new_packet_pointers*sizeof(Array_1));
18
    if(*buffer == NULL) return 1;
19
  }
20
   
21
   /* Allozieren des Speichern für das Paket */
22
   *buffer[packet_number] = malloc(packet_size*sizeof(ArrayType));
23
   if(*buffer[packet_number] == NULL) return 2;
24
   /* Speichern der Daten */
25
   for(; packet_size > 0; packet_size--){
26
     *buffer[packet_number][packet_size] = *(packet + packet_size);
27
   }
28
   return 0;
29
}

PS: den Return Wert von malloc oder realloc in C niemals casten!
Das kann Fehler verstecken. Wenn du casten musst, dann programmierst
du in C++ und dort wäre new/delete anstelle von malloc das Werkzeug
der Wahl, wenn es denn unbedingt selbst programmiert sein soll.
In C++ wäre allerdings std::vector die absolut beste Lösung.

von daniel (Gast)


Lesenswert?

wieso machst du so umständlich?
was spricht hier gegen eine linked list?

verwalte head und tail, und wenn ein packet ankommt
fügst du es am tail an.
dann kannst du eine art konstruktor machen,
der auch nach malloc nach != NULL prüft.
wenn du an 1000 stellen malloc/realloc aufrufst,
ist es oft schwer konsequent zu prüfen.

sollte später sich rausstellen, dass die liste
heterogen sein sollte, kannst du einen tag in
die node stuct nehmen, und entweder einen generischen void*
oder union benutzen.

meine 2 cent
   daniel

von Jorge (Gast)


Lesenswert?

>> Die Funktion von realloc ist nicht überall gleich.
>Unsinn. realloc ist eine Standard-C Funktion. Wenn die nicht
>überall gleich funktioniert, dann ist die betreffende Library
>fehlerhaft und sollte ausgetauscht werden.

:-) Mach es.

Es gibt Unterschiede in der Strategie auch in Abhängigkeit vom 
Betriebssystem. Probleme treten bei starker Fragmentierung und im 
Fehlerfall zutage. Eigentlich sieht es ja überschaubar aus, aber AFAIK 
kann man jede Speicherverwaltung an die Wand fahren.

>http://de.wikipedia.org/wiki/Dynamischer_Speicher

Also realloc zu verwenden bedeutet dem System absolut zu vertrauen und 
die Existenz von Bugs zu verleugnen. Beispielsweise gibt einige gut 
ausgebildete Leute, die von sich geben ein C Compiler könnte "denken". 
Das ist das Gottvertrauen in das System, dem möchte ich hier 
entgegentreten.

Ist natürlich ein Todschlagargument :-)

von COMPILIERENli (Gast)


Lesenswert?

Hallo!

Vielen Dank für die Hilfe. Eine verkettete Liste möchte ich nicht 
verwenden, weil die zu speichernden Daten nicht in einer vorteilhaften 
Reihenfolge ankommen.
Es ist nun so, dass mit dem Simulator eine Stufe weiter komme, aber 
irgendwie scheint das ganze mit dem allozieren immer noch nicht zu 
funktionieren, folgendes habe ich beobachtet:
Wenn ich ein Packet mit nr. 0 (also gleich die erste Stelle) abspeichern 
möchte, dann gibts keine AccessViolation bei <---1. Es geht dann gut bis 
die For-Schleife einmal durchlaufen worden ist und i = 1 ist, dann gibts 
bei <---2 eine AccessViolation. Dies deutet für mich darauf hin, dass 
die Allozierung nicht wirklich funktioniert hat.
Ganz ähnlich verhält es sich wenn die Paketnr. > 0 ist, dann gibts 
bereits bei <---1 eine AccessViolation...
1
#include "stdlib.h"
2
3
4
int nr_of_packets(int **buffer){
5
  /* Gibt die Anzahl allozierte Speicherplätze für Paket-Pointer zurück */
6
  int i = 0;
7
  if(buffer == NULL) return 0;
8
  while(buffer[i++] != NULL);
9
  return i;
10
}
11
12
int save_new_packet(int packet_number, int *packet, int packet_size, int ***buffer){
13
  /* reserviert, falls nötig neue Speicherplätze für Paket-Pointer, und speicher die Daten in packet ab*/
14
  int testvar;
15
  int i;
16
  int new_packet_pointers = packet_number - nr_of_packets(*buffer) + 1;
17
  if(new_packet_pointers > 0){
18
    *buffer = (int **)realloc(*buffer, new_packet_pointers*sizeof(int *));
19
    if(*buffer == NULL) return 1;
20
  }
21
   
22
   /* Allozieren des Speichern für das Paket */
23
   *buffer[packet_number] = malloc(packet_size*sizeof(int));        //<---1
24
   if(*buffer[packet_number] == NULL) return 2;
25
   /* Speichern der Daten */
26
   for(i = 0; i < packet_size; i++){
27
    testvar = *(packet + i);
28
     *buffer[packet_number][i] = testvar;                           //<---2
29
   }
30
   return 0;
31
}
32
33
Wenn da ein Profi noch einen Tipp hat wo der Knopf ist, wäre das sehr schön :)
34
35
int main(){
36
   int **buffer = NULL;
37
   int packet[5]={4,6,7,8,3};
38
   save_new_packet(0, packet, 5, &buffer);
39
}

von COMPILIERENli (Gast)


Lesenswert?

Hoppla eine Zeile stellt kein C-Code dar, wer die Zeile findet darf sie 
behalten...

von Karl H. (kbuchegg)


Lesenswert?

Jorge wrote:
>>> Die Funktion von realloc ist nicht überall gleich.
>>Unsinn. realloc ist eine Standard-C Funktion. Wenn die nicht
>>überall gleich funktioniert, dann ist die betreffende Library
>>fehlerhaft und sollte ausgetauscht werden.
>
> :-) Mach es.

Brauch ich nicht.
Mein realloc funktioniert und ich gehe auch eine Wette ein
dass das realloc vom OP auch funktioniert.
Zumal ein 'simpled' realloc in der Minimalversion absolut
trivial zu implementieren ist.

> Betriebssystem. Probleme treten bei starker Fragmentierung und im
> Fehlerfall zutage.

Wenn du mit realloc Probleme hast, dann hast du die auch mit malloc.
Wenn realloc den Speicher nicht in place vergrößern kann, dann greift
es auf einen normalen malloc (oder auf die darunter liegende
Allokierungsschicht) zurück und macht ein memcpy. Was anderes
kannst du auch nicht machen.

> Also realloc zu verwenden bedeutet dem System absolut zu vertrauen und
> die Existenz von Bugs zu verleugnen.

Mit Verlaub. Aber so einen Unsinn hab ich in 25 Jahren überhaupt
noch nie gehört. In einer Hochsprache zu programmieren heist generell
dem Compiler und dem Runtime System zu vertrauen. Es heist auch
damit leben zu lernen, dass sowohl in Compilern als auch in den
Standard Libraries Fehler vorhanden sind. Das hat aber nichts mit
dem Verleugnen von Bugs zu tun.

Demnächst willst du uns auch noch weiß machen, daß die str...
Funktionen Teufelswerk sind.

von Karl H. (kbuchegg)


Lesenswert?

COMPILIERENli wrote:
> möchte, dann gibts keine AccessViolation bei <---1. Es geht dann gut bis
> die For-Schleife einmal durchlaufen worden ist und i = 1 ist, dann gibts
> bei <---2 eine AccessViolation. Dies deutet für mich darauf hin, dass
> die Allozierung nicht wirklich funktioniert hat.
> Ganz ähnlich verhält es sich wenn die Paketnr. > 0 ist, dann gibts
> bereits bei <---1 eine AccessViolation...

Na ja.
Deine nr_of_packets Funktion ist darauf angewiesen, dass du immer
einen Pointer mehr als benötigt allozierst, damit ganz zum Schluss
am Ende des Arrays ein NULL Pointer steht. Diesen NULL Pointer
benutzt nr_of_packets um das Ende des Arrays zu finden.

Blöd ist nur, dass du diesen NULL Pointer niemals im Array setzt.

Hinweis: Mit deiner Abzählstrategie musst du immer einen Pointer
mehr allokieren als du eigentlich Pointer im Array speicherst.
Wenn du den ersten Pointer ins Array legst, musst du Platz für
2 Pointer allokieren. Den ersten für den tatsächlichen Datenpointer,
den zweiten für den NULL Pointer nach dem nr_of_packets sucht.

Mein Tip an dich lautet:
Papier und Bleistift raus und einfach mal mitzeichnen, welcher
Pointer wann und wo gesetzt wird und dann einfach mal Computer
spielen und das ganze am Papier durcharbeiten. Dann sollte es klarer
werden.

Und immer dran denken: Wenn du Speicher allokierst, dann ist
(mit Ausnahme von calloc) nicht vorherbestimmt, welche Werte
bereits in diesem Speicher stehen. malloc(), realloc() setzen
den Speicher nicht auf 0!

von Jorge (Gast)


Lesenswert?

Hallo Karl heinz,

ich möchte dir keinesfalls zu nahe treten.

>Mit Verlaub. Aber so einen Unsinn hab ich in 25 Jahren überhaupt
>noch nie gehört. In einer Hochsprache zu programmieren heist generell
>dem Compiler und dem Runtime System zu vertrauen.

Du hast ja auch recht mit deinen Aussagen. Es gibt aber eine Sichtweise 
unabhängig von Bit und Byte und das hat wie du es auch schon 
angesprochen hast etwas mit der Persönlichkeit des Programmierers zu 
tun. Jeder hat natürlich seinen individuellen Stil und kommt damit 
zurecht.

Im Team habe ich Leute kennengelernt, die sich früher oder später einen 
anderen Traumjob suchen. Genau wie du bin ich aber meiner Linie treu 
geblieben, egal ob mir jemand etwas dafür zahlt oder nicht.

Ein Punkt beim realloc ist, daß es etwas komplizierter ist, sich in die 
Gedankengänge eines fremden Programmierers einzufinden. Es sind halt ein 
paar Parameter mehr und man weiss nicht sofort was hat der/die sich 
dabei gedacht.

Ich dachte mir spontan, der Fragesteller benutzt eine Vorlage, mit einem 
Repertoire welches er nicht beherrscht - und ist daran gescheitert.


Analog zu new und delete benutze ich spartanisch die Heapfunktionen wie 
Compund-statements in einem Block. Ich möchte völlig klar wissen welches 
Fragment wann erzeugt und freigegeben ist. In einem 2-dimensionalen 
Array werden bei mir erst sämtliche Pointer für die 1-te Dimension 
erzeugt und in einer zweiten Schleife die Pointer für die 2-te 
Dimension. Selbstverständlich kann man auch alles in einer Schleife und 
innerhalb einer Zeile erledigen. Manchmal gehe ich aus garantierten 
Performancegründen sogar soweit, dass ich einen grossen Block anfordere 
und die Fragmente via Pointerarithmetik selbst verwalte, am Schluss wird 
nur noch mit einem free bzw delete aufgeräumt. Gerade innerhalb von 
Klassen mach ich es so. Jedermann weiss warum Java irgendwann so langsam 
wird. Auch das Argument der hängenden Pointer, welches vor allem von 
ungeschickten Programmierern immer wieder ins Feld geführt wird verliert 
seinen Gehalt.

Wenn jemand den Umgang mit realloc aus dem ff beherrscht darf er das 
gerne verwenden, mir ist es unsympathisch weil es eine Funktion mehr ist 
und gegen die Kreativität nach dem Legoprinzip funktioniert, also immer 
der gleiche simple Baustein in kreativer Weise eingesetzt. Weiterhin 
sind ein paar mehr Fehlerbedingungen beim realloc zu berücksichtigen. 
Die errno Variable gibt zurück, ob die Anforderung erfolgreich war. Bei 
new oder alloc muss ich nur gucken, ob das Ergebnis ungleich NULL ist.

Leider kann man sich im Windoof und heutzutage auch im 
Distributionslindoof auf gar nix mehr verlassen. Die Heapfunktionen 
werden mehr oder minder ans Betriebssystem weitergereicht, schon aus der 
Win311 Ära ist es mir gründlich verleidet.

Besonders aufschlussreich war mir die Zeit als Programmierer im Team mit 
Leuten, die deutlich weniger Erfahrung und erfolgreiche Projekte haben. 
Dafür hatten die aber bessere Noten. Ich habe mich niemals eingemischt, 
es ist durchaus möglich, dass ich für deren Konstruktion schlicht zu 
blöd bin.

Der Grundfehler an dem solche Leute letztlich an psychischer 
Überbelastung scheitern ist es Strukturen azulegen die komplizierter 
sind als sie es selbst durchschauen.

Deswegen mein Nein zu realloc & Co.

von Arc N. (arc)


Lesenswert?

Das eigentliche Problem ist die ursprünglichen Frage, da die wichtigsten 
Angaben fehlen, um entscheiden zu können welcher Ansatz verwendet werden 
sollte.
Wie oft wird das Anlegen benötigt, wie viele Objekte, wie müssen die 
Objekte danach weiterverarbeitet werden etc.? Steht das fest, kann man 
entscheiden wie man's implementiert: mit einfachen Arrays, Listen oder 
z.B. Heaps. Ist dann die Speicherallokation das limitierende Element, 
kann man diese anpassen.

p.s. Ein "kleiner" Test für Speicherverwaltungsalgorithmen war die 
grundlegende VM des ICFPCs 2006, die man auch für einen 
Performance-Vergleich nehmen könnte...
http://www.boundvariable.org/um-spec.txt

von COMPILIERENli (Gast)


Lesenswert?

Hallo!

Also eigentlich würde ich schon gerne auf eine Hochsprache mit ihren 
Vorzügen vertrauen...
Zu den Anforderungen: Es geht darum, dass einzelne Pakete ankommen, in 
der Grösse von max. einigen Kb, jedoch in einer beliebigen Reihenfolge. 
Diese sollen abgelegt werden, und zwar so, dass man weiss, welche Pakete 
noch fehlen. Am Schluss sollen dann alle Pakete aneinander gehängt 
werden.
Ich kenne nicht alle Möglichkeiten wie man so etwas realisieren könnte, 
aber Heap und Linked List scheinen mir nicht die richtigen Mittel zu 
sein (lehrt mich was besseres, wenn dies nicht stimmt).
Wenn ich jetzt meinen Code betrachte, dann müsste ich die Pointer nach 
dem erstellen jeweils mit NULL initialisieren, so dass ich nachher 
überprüfen kann ob an einer Stelle schon ein Paket abgelegt ist oder 
nicht?!
Wenn ich die Funktion nr_of_packets so abändere, dass immer 0 zurück 
gegeben wird, und eigentlich jedes Mal so quasi zur Sicherheit neue 
Paket-Pointer erstellt werden (was sicher nicht sehr gut ist, aber mal 
zum Testen woran es liegt) dann werden zwar sehr brav immer neue 
Pakete-Pointer erstellt, aber bei <---1 gibt es trotzdem eine Access 
Violation, wenn ich das Paket nr 1 erstellen will. Deshalb glaube ich 
immer noch, dass vorher (beim realloc) was schief gehen muss, denn 
aufgerufen wird dies zwar aber irgendwie macht es nicht das was es 
soll?!
Danke für Eure Geduld!

von Karl H. (kbuchegg)


Lesenswert?

Jorge wrote:

> Du hast ja auch recht mit deinen Aussagen. Es gibt aber eine Sichtweise
> unabhängig von Bit und Byte und das hat wie du es auch schon
> angesprochen hast etwas mit der Persönlichkeit des Programmierers zu
> tun. Jeder hat natürlich seinen individuellen Stil und kommt damit
> zurecht.

Du philosophierst mir hier zuviel.
Daher möchte ich meinen Standpunkt wie folgt zusammenfassen:
Ich glaub dir schon, dass du auf dem einen oder anderen System
mal in Schwierigkeiten mit der Library Implementierung für
realloc gestossen bist.
Daraus aber die generelle Empfehlung abzuleiten, realloc nicht
zu benutzen, ist weit, weit, weit über das Ziel hinausgeschossen.

> Wenn jemand den Umgang mit realloc aus dem ff beherrscht darf er das
> gerne verwenden,

Wenn jemand mit malloc und free klar kommt, gibt es keinen Grund
auf realloc zu verzichten. Kommt er mit realloc nicht klar, dann
kommt er auch nicht mit malloc/free bzw. dynamischer Speicher-
verwaltung nicht klar. Da es aber in C keine Alternative dazu gibt
(Alles am Stack statisch zu allokieren ist keine Alternative),
muss er den Umgang mit dynamischen Strukturen lernen. Das hat aber
nichts mit realloc an sich zu tun.

von Karl H. (kbuchegg)


Lesenswert?

COMPILIERENli wrote:

> Ich kenne nicht alle Möglichkeiten wie man so etwas realisieren könnte,
> aber Heap und Linked List scheinen mir nicht die richtigen Mittel zu
> sein (lehrt mich was besseres, wenn dies nicht stimmt).

Linked List wäre nicht schlecht. Aber deine gewählte Systematik
geht auch.

> Wenn ich jetzt meinen Code betrachte, dann müsste ich die Pointer nach
> dem erstellen jeweils mit NULL initialisieren,

Nein.
Es geht um die Funktion nr_of_packets. Die hast doch du
geschreiben, oder nicht?
Was macht die?
Sie geht das Pointer Array durch um rauszufinden wie gross das
Array ist. Soweit so gut. Aber woran erkennt sie denn das Ende
des Arrays? Indem dort ein NULL Pointer stehen muss.
zb. so was

   +---------+
   |   o------------------->  Daten
   +---------+
   | NULL    |
   +---------+

Merkst du was?
Du hast einen Nutzpointer, der auf Daten zeigt. Und zusätzlich
benötigst du noch einen NULL Pointer im Array, der das Ende
markiert. Bei 1 Nutzpointer, muss das Pointerarray also für
2 Pointer allokiert werden.

Das macht deine Allokierungsfunktion aber nicht. Und daher kann
nr_of_packets die Arraygröße nicht richtig bestimmen und daher
kommt dann in weiterer Folge alles durcheinander.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.