Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...
-
#include <stdio.h> #include <stdlib.h> typedef struct Node { struct TNode *next; char *content; int len; } TNode; TNode *root = 0; int len = 0; TNode *get_nth(int n) { TNode *tn = root; int i = 0; for (; i < len && i < n; i++) { root = (TNode *)root->next; } return tn; } void insert(int n, char *content, int l) { TNode *tn0 = get_nth(n - 1); TNode *tn1 = get_nth(n); TNode *tn2 = 0; if (tn0 == 0) { tn2 = malloc(sizeof(TNode)); tn2->content = content; tn2->len = l; if (tn1 != 0) tn2->next = (struct TNode *)tn1; else tn2->next = 0; root = tn2; } else { tn2 = malloc(sizeof(TNode)); tn2->content = content; tn2->len = l; if (tn1 != 0) tn2->next = (struct TNode *)tn1; else tn2->next = 0; tn0->next = (struct TNode *)tn2; } len++; } int main(int argc, char **argv) { int i = 0; TNode *tn = 0; insert(0, "hallo 1", 7); insert(1, "hallo 2", 7); insert(0, "hallo 3", 7); for (; i < len; i++) { tn = get_nth(i); printf("%s\n", tn->content); } return 0; }
Ich erhalte folgende Ausgabe:
$ ./LinkedList.out hallo 3 hallo 3 Speicherzugriffsfehler (Speicherabzug geschrieben)
Sieht ein geübtes Auge evtl schnell den Fehler?
-
Hab den Fehler gerade in der Funktion
get_nth(int n)
gefunden:TNode *get_nth(int n) { TNode *tn = root; int i = 0; if (n < 0) return 0; for (; i < len && i < n; i++) { tn = (TNode *)tn->next; } return tn; }
-
@EinNutzer0
Jup, sehe den Fehler. Variable root ist anfangs 0.
-
@Quiche-Lorraine Also das Problem war...
get_nth
sollte mit -1 nicht root zurückgeben, sondern 0
-
@EinNutzer0
Aber der zweite get_nth() Aufruf wird beim ersten insert() mit 0 aufgerufen.
-
@EinNutzer0
Sorry stimmt nicht was ich gesagt habe.
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
insert(0, "hallo 1", 7); insert(1, "hallo 2", 7); insert(0, "hallo 3", 7);
Warum nutzt der letzte insert Befehl den Index 0?
-
@Quiche-Lorraine Hier ist das nochmal "geglättet":
#include <stdio.h> #include <stdlib.h> typedef struct Node { struct TNode *next; char *content; int len; } TNode; TNode *root = 0; int len = 0; TNode *get_nth(int n) { TNode *tn = root; int i = 0; if (n < 0) { return 0; } for (; i < len && i < n; i++) { tn = (TNode *)tn->next; } return tn; } void insert(int n, char *content, int l) { TNode *tn0 = get_nth(n - 1); TNode *tn1 = get_nth(n); TNode *tn2 = 0; if (tn0 == 0) { tn2 = malloc(sizeof(TNode)); tn2->content = content; tn2->len = l; tn2->next = (struct TNode *)tn1; root = tn2; } else { tn2 = malloc(sizeof(TNode)); tn2->content = content; tn2->len = l; tn2->next = (struct TNode *)tn1; tn0->next = (struct TNode *)tn2; } len++; } int main(int argc, char **argv) { int i = 0; TNode *tn = 0; insert(0, "hallo 1", 7); insert(1, "hallo 2", 7); insert(2, "hallo 3", 7); insert(0, "hallo 0", 7); for (; i < len; i++) { tn = get_nth(i); printf("%s\n", tn->content); } return 0; }
Nu funktioniert es, insert() soll den content an Stelle n einfügen...
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
root = (TNode *)root->next;
Jetzt sehe ich den Fehler.
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
struct TNode *next;
Das ist doch Quatsch oder?
struct Node
!In Zeile 39 machst Du den selben Blödsinn nochmal ähnlich.
Allgemein schaut das alles viel zu komplifiziert aus.
-
@Swordfish Du hast recht... Aber wieso funktioniert das dennoch?!
Ist mir beim pasten auch nicht aufgefallen... o.O
-
Weil das einfach eine struct deklariert die nichts mit der definierten
Node
zu tun haben. Pointer sizes werden wohl die selben sein, deshalb "funktioniert" es.
Aber allgemein: Du vermischt da komplett die Zuständigkeiten. Ein String ist keine Node. Eine Node ist keine List. Modelliere jedes einzelteil für sich.
-
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Eine Node ist keine List
doch...
Ich hab jetzt die Zuständigkeiten getrennt... Aber jetzt bekomme ich immer eine
Gleitkomma-Ausnahme (Speicherabzug geschrieben)
zwischen Zeile 94 und 98. Ich vermute es liegt amsprintf
aber sicher bin ich mir nicht. Kann noch mal jemand schauen?#include <stdio.h> #include <stdlib.h> struct ByteContent { char *content; int len; }; struct Node { struct Node *next; struct ByteContent *byte_content; }; struct Node *root = 0; int len = 0; struct Node *get_nth(int n) { struct Node *tn = root; int i = 0; if (n < 0) { return 0; } for (; i < len && i < n; i++) { tn = tn->next; } return tn; } struct ByteContent *get_byte_content(int n) { return get_nth(n)->byte_content; } void insert(int n, struct ByteContent *bc) { struct Node *tn0 = get_nth(n - 1); struct Node *tn1 = get_nth(n); struct Node *tn2 = 0; if (tn0 == 0) { tn2 = malloc(sizeof(struct Node)); tn2->byte_content = bc; tn2->next = tn1; root = tn2; } else { tn2 = malloc(sizeof(struct Node)); tn2->byte_content = bc; tn2->next = tn1; tn0->next = tn2; } len++; } struct ByteContent *delete (int n) { struct Node *tn0 = 0; struct Node *tn1 = 0; struct ByteContent *a = 0; if (n < 0 || n >= len) { return 0; } tn0 = get_nth(n - 1); tn1 = get_nth(n); a = tn1->byte_content; if (tn0 == 0) { root = root->next; } else { tn0->next = tn1->next; } free(tn1); len--; return a; } int main(int argc, char **argv) { int i = 0; struct ByteContent *temp = 0; struct ByteContent **bc = malloc(sizeof(struct ByteContent *) * 10); char *ca = 0; for (i = 0; i < 10; i++) { bc[i] = malloc(sizeof(struct ByteContent)); ca = (char *)malloc(sizeof(char) * 9); sprintf(ca, "hallo %d!", i); bc[i]->content = ca; bc[i]->len = 9; } for (i = 0; i < 10; i++) { insert(rand() % len, bc[i]); } for (i = 0; i < 10; i++) { delete (rand() % len); } for (i = 0; i < 10; i++) { insert(rand() % len, bc[i]); } for (i = 0; i < len; i++) { temp = get_byte_content(i); printf("%s\n", temp->content); } return 0; }
-
Welchen wert hat
len
in Zeile 102?
-
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Welchen wert hat
len
in Zeile 102?0, ist ja noch leer...
-
Dann brauchst du dich auch nicht über den Fehler bei
rand() % len
wundern (intern wird bei Modulo ja auch eine Division durchgeführt)...
-
Danke, jetzt funktioniert es:
#include <stdio.h> #include <stdlib.h> struct ByteContent { char *content; int len; }; struct Node { struct Node *next; struct ByteContent *byte_content; }; struct Node *root = 0; int len = 0; struct Node *get_nth(int n) { struct Node *tn = root; int i = 0; if (n < 0) { return 0; } for (; i < len && i < n; i++) { tn = tn->next; } return tn; } struct ByteContent *get_byte_content(int n) { return get_nth(n)->byte_content; } void insert(int n, struct ByteContent *bc) { struct Node *tn0 = get_nth(n - 1); struct Node *tn1 = get_nth(n); struct Node *tn2 = 0; if (tn0 == 0) { tn2 = (struct Node *)malloc(sizeof(struct Node)); tn2->byte_content = bc; tn2->next = tn1; root = tn2; } else { tn2 = (struct Node *)malloc(sizeof(struct Node)); tn2->byte_content = bc; tn2->next = tn1; tn0->next = tn2; } len++; } struct ByteContent *delete (int n) { struct Node *tn0 = 0; struct Node *tn1 = 0; struct ByteContent *a = 0; if (n < 0 || n >= len) { return 0; } tn0 = get_nth(n - 1); tn1 = get_nth(n); a = tn1->byte_content; if (tn0 == 0) { root = root->next; } else { tn0->next = tn1->next; } free(tn1); len--; return a; } int main(int argc, char **argv) { int i = 0; struct ByteContent *bc[10]; char *ca = 0; struct ByteContent *temp = 0; for (i = 0; i < 10; i++) { bc[i] = (struct ByteContent *)malloc(sizeof(struct ByteContent)); ca = (char *)malloc(sizeof(char) * 9); sprintf(ca, "hallo %d!", i); bc[i]->content = ca; bc[i]->len = 9; } for (i = 0; i < 10; i++) { insert(rand() % (len + 1), bc[i]); } for (i = 0; i < 10; i++) { delete (rand() % len); } for (i = 0; i < 10; i++) { insert(rand() % (len + 1), bc[i]); } for (i = 0; len > 0; i++) { temp = delete (0); printf("%s\n", temp->content); free(temp->content); free(temp); temp = 0; } /* * Überprüfe, ob Heap leer ist...? */ return 0; }
Kann ich am Ende irgendwie feststellen, ob der Heap leer ist?
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Kann ich am Ende irgendwie feststellen, ob der Heap leer ist?
-
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Geil!
#include <stdio.h> #include <stdlib.h> struct ByteContent { char *content; int len; }; struct Node { struct Node *next; struct ByteContent *byte_content; }; struct Node *root = 0; int len = 0; struct Node *get_node(int n) { struct Node *tn = root; int i = 0; if (n < 0) { return 0; } for (; i < len && i < n; i++) { tn = tn->next; } return tn; } struct ByteContent *get_byte_content(int n) { if (n < 0 || n >= len) { return 0; } return get_node(n)->byte_content; } void insert(int n, struct ByteContent *bc) { struct Node *tn0 = get_node(n - 1); struct Node *tn1 = get_node(n); struct Node *tn2 = 0; if (n < 0 || n > len || bc == 0) { return; } tn2 = (struct Node *)malloc(sizeof(struct Node)); tn2->byte_content = bc; tn2->next = tn1; if (tn0 == 0) { root = tn2; } else { tn0->next = tn2; } len++; } struct ByteContent *delete (int n) { struct Node *tn0 = 0; struct Node *tn1 = 0; struct ByteContent *temp = 0; if (n < 0 || n >= len) { return 0; } tn0 = get_node(n - 1); tn1 = get_node(n); temp = tn1->byte_content; if (tn0 == 0) { root = root->next; } else { tn0->next = tn1->next; } free(tn1); len--; return temp; } int main(int argc, char **argv) { int i = 0; struct ByteContent *byte_array[10]; char *content = 0; struct ByteContent *temp = 0; for (i = 0; i < 10; i++) { byte_array[i] = (struct ByteContent *)malloc(sizeof(struct ByteContent)); content = (char *)malloc(sizeof(char) * 9); sprintf(content, "hallo %d!", i); byte_array[i]->content = content; byte_array[i]->len = 9; } for (i = 0; i < 10; i++) { insert(rand() % (len + 1), byte_array[i]); } for (i = 0; i < 10; i++) { delete (rand() % len); } for (i = 0; i < 10; i++) { insert(rand() % (len + 1), byte_array[i]); } for (i = 0; len > 0; i++) { temp = delete (0); printf("%s\n", temp->content); free(temp->content); free(temp); temp = 0; } /* * Let Valgrind do it's work... */ return 0; }
$ valgrind --leak-check=yes ./LinkedList.out ==6482== Memcheck, a memory error detector ==6482== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==6482== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==6482== Command: ./LinkedList.out ==6482== hallo 2! hallo 8! hallo 3! hallo 5! hallo 7! hallo 9! hallo 4! hallo 1! hallo 6! hallo 0! ==6482== ==6482== HEAP SUMMARY: ==6482== in use at exit: 0 bytes in 0 blocks ==6482== total heap usage: 41 allocs, 41 frees, 1,594 bytes allocated ==6482== ==6482== All heap blocks were freed -- no leaks are possible ==6482== ==6482== For lists of detected and suppressed errors, rerun with: -s ==6482== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Jetzt hab ich eine bombensichere Liste.
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Jetzt hab ich eine bombensichere Liste.
Werd' mal die gobalen Variablen los,
typedef
s für die Structs, Variablen so lokal wie möglich deklarieren,sizeof(*ptr)
stattsizeof(explicit_type)
, ...