Hallo!
Ich hab ein Problem, hinter welches ich einfach nicht komm, obwohl's
wahrscheinlich sehr einfach zu lösen ist.
Und zwar lese ich aus einer Binärdatei Datensätze aus (haben alle
bestimmte Form aus Header und beliebig langen Content).
Nun schaffe ich es nicht, dass ich, nachdem ich einen Datensatz in das
1. Listenelement gespeichert habe, auf das nächste Listenelement zu
springen.
Wenn ich am Ende der While-Schleife, die zum Einlesen eines Datensatzes
dient, folgendes schreibe:
dann bekomme ich jedes Mal einen Segmentation Fault -_-
Wie macht man das, dass man nach dem fertigen Hineinspeichern in das 1.
Element auf das nächste springt?
So sieht mein Struct aus, das sollte so passen.
Im Programm mach ich jetzt 3 mal fread, einmal für den immer gleich
großen Header, und zweimal für die beiden variabel langen strings.
1
typedefstruct_Header_
2
{
3
unsignedintidentifier;
4
doublelatitude;
5
doublelongitude;
6
unsignedintcontent_length;
7
}
8
Header;
9
10
typedefstruct_Content_
11
{
12
char*place_name;
13
char*description;
14
}
15
Content;
16
17
typedefstruct_List_
18
{
19
struct_List_*next;
20
Headerheader;
21
Contentcontent;
22
}
23
List;
so im Programm unterhalb definiere ich dann in der Einlesefunktion die
Liste.
dann mach ich halt die mallocs für den Header, und die beiden Strings
und lies nach jedem malloc ein.
Zerf schrieb:> Such mal mit dem Debugger die Stelle, an der der Segfault auftritt. Dann> geht Dir sicher ein Licht auf.
Wies weiter geht, das weiß ich nicht bzw. schaffe ich es nicht, das
herauszufinden, das kann doch kein Problem sein für euch, bitte helft
mir!
>.... malloc, fread bla bla bla
ist doch ein bisschen lakonisch und bei der Aufzählung
>dann mach ich halt die mallocs für den Header, und die beiden Strings
vermisse ich das malloc für das Listenelement selbst.
Ich sehe hier bloss Zeiger.
Zeig mal den kompletten Code. Reduziere ihn auf das Notwendigste, so das
der Fehler noch auftritt.
>Wies weiter geht, das weiß ich nicht bzw. schaffe ich es nicht, das>herauszufinden, das kann doch kein Problem sein für euch, bitte helft>mir!
Ist langfristig sowieso keine Lösung. Du kannst ja nicht jedesmal wenn
ein Problem auftritt sagen: "Ich kann keinen Debugger bedienen, da frag
ich in mikrocontroller.net".
...nimm den Debugger, kämpf Dich bis zum Segfault und schau Dir die
Pointer (also deren "Wert") an. Was willst du mit
"first_element_of_single_linked_list =
first_element_of_single_linked_list->next;" erreichen?
Zerf schrieb:> Was willst du mit> "first_element_of_single_linked_list => first_element_of_single_linked_list->next;" erreichen?
Ich will damit nach dem Einlesen eines Binärfile-Datensatzes auf das
nächste Element der Liste springen.
Ich weiß eben nicht, ob ich, wenn ich im nächsten Schleifendurchlauf bin
und dort wieder ein malloc(sizeof(List)) mache, ob ich ohne die
Codezeile von oben dann im nächsten Feld der Liste bin oder den
vorherigen Eintrag überspeichere oder ins 1. Element der Liste noch
einen zweiten Datensatz hineinspeichere.
Ich möchte Dir ernsthaft empfehlen hier den vollständigen Code zu
zeigen. Deine Erklärungen sind unklar, wozu nicht unwesentlich die
Identifizierung Deiner Person mit dem Programm und mit Variablen
beiträgt.
Reduziere ihn auf das zum traversieren der Liste und hinzufügen von
Elementen notwendige ohne das Einlesen der Strings. Das hinzufügen muss
auch ohne das funktionieren.
Die sollte ganz unten vor dem Ende der do/while, nur wie schon jetz sehr
oft von mir gesagt, ich weiß nicht, ob man die braucht. Diese Funktion
liest Element für Element ein, aber speichert sie diese auch
nacheinander in die Liste? Das will ich beantwortet haben!
aja, ich hab das mit first_element_of_single_linked_list ins list
umändern wolln, das steht aber leider noch 2-3 mal im code, soll beides
das gleiche sein!
Das kann ja sein, aber ein L-Value der Form list->next erscheint
nirgends.
Ich bitte Dich ein letztesmal, vollständigen, auf das notwendigste
(Listenverkettung) Code zu posten und setzt hinzu das er kompilierbar
sein muss.
So hat das keinen Zweck.
Ooops.
Es muss natürlich heissen:
Ich bitte Dich ein letztesmal, vollständigen, auf das notwendigste
(Listenverkettung) reduzierten Code zu posten und setze hinzu das er
kompilierbar
sein mu
So ich hab jetzt eine halbe Stunde lang gegoogelt und bin darauf
gekommen, dass ich in meinem Programm ganz oben ja die Funktion
*error_code = allocateListMemory(&list);
aufrufe, welche den Befehl
1
list=malloc(sizeof(List));
beinhaltet.
Mit diese malloc(sizeof(List)) füge ich ja schon ein neues Element ein
und diese Zeile mit
list = list->next;
ist ein Schwachsinn bzw. nicht notwendig.
Johannes M. schrieb:> Mit diese malloc(sizeof(List)) füge ich ja schon ein neues Element ein> und diese Zeile mit> list = list->next;> ist ein Schwachsinn bzw. nicht notwendig.
trotzdem macht sich die Verpointerung nicht von allein.
Mein Tip:
Trenne Nutzdaten und Struktur!
KApsel das Listeninterface gescheit
Dann wird das ganze auch übersichtlich
Denke dir die Typdefs bitte selbst dazu
1
structList
2
{
3
ListElement*first;
4
ListElement*last;
5
}
6
7
8
structListElement
9
{
10
ListElement*next;
11
void*data;
12
}
13
14
/**
15
* adds an element at the end of the list
16
* @param list the list to manipulate
17
* @param data pointer to the data to add
18
*/
19
voidList_pushBack(List*list,void*data)
20
{
21
ListElement*e=malloc(sizeof(ListElement));
22
if(list->last!=0){
23
list->last.next=e;
24
}else{
25
list->first=e;
26
}
27
e->next=0;
28
e->data=data;
29
list->last=e;
30
}
31
32
/**
33
* adds an element at the front of the list
34
* @param list the list to manipulate
35
* @param data pointer to the data to add
36
*/
37
voidList_pushFront(List*list,void*data)
38
{
39
ListElement*e=malloc(sizeof(ListElement));
40
e->next=list->first;
41
e->data=data;
42
if(list->last==0){
43
list->last=e;
44
}
45
list->first=e;
46
}
47
48
49
/**
50
* frees the memory of all *following (next)* list elemnt.
51
* @param le pointer to listelement
52
* if the first listelement of a list should be deleted
53
* the list pointer can be casted to an Listelement*
54
* @param deleteContent if true also the data of the list elemnt will be freed
55
* obviously this only work on plain data structures with no
Entschuldige.
Aber das ist doch alles Mist!
Trenne die Dinge auf!
Mach dir eine Funktion, der du eine Datenstruktur übergibst und die
diese Datenstruktur vom File befüllt.
Es ist nicht Aufgabe dieser Funktion, dieses Datenelement dann auch noch
in die Liste einzuhängen! Das geschieht an einer anderen Stelle!
Du schreibst da endlos lange Funktionen und dann wunderst du dich, wenn
du den Überblick verlierst.
Ich hab dir doch beim letzten mal schon so ungefähr eine sinnvolle
Struktur gegeben. Ich mach das doch nicht zum Spass und weil draussen
das Wetter so schön ist.
Eines der 'Geheimnisse' der Programmierung besteht darin, dass man sich
Struktur in den Code bringt. Struktur im Sinne von 'Aufteilung in
Teilprobleme und jedes Teilproblem wird zu einer Funktion'. So kann man
das Biest "Unübersichtlichkeit" bekämpfen und unter Kontrolle bringen.
Aber doch nicht, indem man alles in möglichst eine einzige Funktion
reinquetscht. Und dann auch noch mehrfach (wie zb das Einlesen eines
Strings).
Gerade Neulinge glauben oft: Ja, aber wenn ich das jetzt erst mal in
Teilfunktionen aufteile, dann brauch ich so lang bis ich fertig
programmiert habe.
Das genaue Gegenteil ist der Fall! Du brauchst 10-fach länger, wenn du
NICHT gleich organisiert an die Dinge ran gehst. Denn du wirst die
Übersicht verlieren. Das ist 100% sicher! So ein Wunderwuzzi bist du
nicht, dass bei dir alles ganz anders ist, wie bei den restlichen
weltweit 20-tausend Programmierer, die jetzt im Moment genau das gleiche
vorhaben.