Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...
-
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)
, ...
-
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
typedef
s für die Structs,Dafür bräuchte ich ein Header file... (wegen Vorwärtsdeklaration)
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Variablen so lokal wie möglich deklarieren,
Wäre nicht mehr Ansi-C!
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
sizeof(*ptr)
stattsizeof(explicit_type)
,Stimmt!
@Swordfish sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Werd' mal die gobalen Variablen los,
Aber wie?
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Dafür bräuchte ich ein Header file... (wegen Vorwärtsdeklaration)
Unsinn.
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Wäre nicht mehr Ansi-C!
Unsinn.
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Aber wie?
Dafür haben die C-Götter Parameter erfunden.
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Ansi-C!
und wenn wir schon beim Thema sind auch die ganzen sinnfreien Pointer casts.
-
@Wutz sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Unsinn.
Nein, ist es nicht; denn wenn ich so etwas schreibe:
struct Node; /* forward declaration */ typedef struct Node TNode; /* forward declaration */ /* implementation... */
bekomme ich eine Compilerwarnung, und das Ganze darf KEINE Warnungen enthalten.
Ebenso müssen die lokalen Variablen zu Beginn der Funktion deklariert werden, damit C nicht meckert.
(
-ansi -pedantic -Wall
)
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
damit C nicht meckert.
wie wär's mit alles neuer als C89?
-
Wenn schon C dann richtiges C @Swordfish @Wutz
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
richtiges C
Schau' mal auf den Kalender.
-
@EinNutzer0 sagte in Speicherzugriffsfehler (Speicherabzug geschrieben), was ist falsch...:
Wenn schon C dann richtiges C @Swordfish @Wutz
Also K&R!