Προς το περιεχόμενο

Προβλημα με λιστα στη C


HouseMusicFan

Προτεινόμενες αναρτήσεις

  • Απαντ. 34
  • Δημ.
  • Τελ. απάντηση
Δημοσ.

Πάντως οφείλω να το ομολογήσω οτι επιτέλους βλέπω έναν topic starter ο οποίος γράφτηκε πιστεύω με μοναδικό λόγο να ρωτήσει κάτι, και δεν περίμενε την απάντηση έτοιμη απο εμάς. Τελευταία (υποθέτω λόγω εξεταστικής περιόδου) είχα αρχίσει να εκνευρίζομαι με όλες τι εκφωνήσεις ασκήσεων.

 

λίγο offtopic...

 

 

 

Πες τα!!!

 

 

Εδώ ο άλλο ζήτησε την λύση ενώ έγραφε εξετάσεις!

Δημοσ.

Τι εννοείς δεν σου χρειάζεται; Δεν επιδέχεται "μου χρειάζεται, δεν μου χρειάζεται"... κάθε πετυχημένο malloc()/calloc() πρέπει υποχρεωτικά να συνοδεύεται από αντίστοιχο free() πριν τον τερματισμό του προγράμματος.

 

Η μνήμη που δεσμεύουν τα malloc()/calloc() δεσμεύεται στο heap της RAM (και όχι στο stack), οπότε είναι υποχρέωσή σου να την αποδεσμεύσεις πριν επιστρέψεις στο λειτουργικό σύστημα. Δεν μπορείς να εμπιστευτείς πως θα την καθαρίσει αντί για σένα το λειτουργικό σύστημα, γιατί δεν είναι υποχρεωμένο να το κάνει (άσχετα αν συχνά το κάνει, έστω και περιοδικά με garbage collection, το οποίο btw καθυστερεί όλο σου το σύστημα).

 

Αν δεν κάνεις free τη μνήμη που δεσμεύεις, αργά ή γρήγορα τα προγράμματά σου θα δημιουργήσουν memory leaks, τα οποία έχουν τη δυναμική να επηρεάσουν αρνητικά όχι μόνο άλλα προγράμματα άσχετα με το δικό σου, αλλά και το ίδιο το λειτουργικό σύστημα.

 

Πες τα!!!

 

 

Εδώ ο άλλο ζήτησε την λύση ενώ έγραφε εξετάσεις!

Μη μου το θυμίζεις!!! Πώς την πάτησα έτσι :(

Δημοσ.

Τι εννοείς δεν σου χρειάζεται; Δεν επιδέχεται "μου χρειάζεται, δεν μου χρειάζεται"... κάθε πετυχημένο malloc()/calloc() πρέπει υποχρεωτικά να συνοδεύεται από αντίστοιχο free() πριν τον τερματισμό του προγράμματος.

 

Η μνήμη που δεσμεύουν τα malloc()/calloc() δεσμεύεται στο heap της RAM (και όχι στο stack), οπότε είναι υποχρέωσή σου να την αποδεσμεύσεις πριν επιστρέψεις στο λειτουργικό σύστημα. Δεν μπορείς να εμπιστευτείς πως θα την καθαρίσει αντί για σένα το λειτουργικό σύστημα, γιατί δεν είναι υποχρεωμένο να το κάνει (άσχετα αν συχνά το κάνει, έστω και περιοδικά με garbage collection, το οποίο btw καθυστερεί όλο σου το σύστημα).

 

Αν δεν κάνεις free τη μνήμη που δεσμεύεις, αργά ή γρήγορα τα προγράμματά σου θα δημιουργήσουν memory leaks, τα οποία έχουν τη δυναμική να επηρεάσουν αρνητικά όχι μόνο άλλα προγράμματα άσχετα με το δικό σου, αλλά και το ίδιο το λειτουργικό σύστημα.

 

Δεν θέλω να πω οτι κάνεις λάθος, περισσότερο να συμπληρώσω θέλω και να πω την άποψή μου.

Φυσικά και πρέπει να κάνουμε free() πάντα στο πρόγραμμα μας για να μην έχουμε memory leak για όσο τρέχει όμως. Προς θεού αυτό δε σημαίνει οτι μπορούμε να μην κάνουμε free αλλα πιστεύω το λειτουργικό σύστημα ΕΙΝΑΙ υποχρεωμένο να το κάνει μετά το τελος λειτουργίας του προγράμματος, για το αν αργεί η διαδικασία, υπεύθυνος είναι ο σχεδιαστής του λειτουργικού και όχι ο χρήστης του.

Δημοσ.

Παιδια θα γινει και το free μολις ολοκληρωθει το project παρολο που με βαση τις οδηγιες του κα8ηγητη δεν ειναι απαραιτητο!

 

Ευχαριστω παντως πολυ για τη βοηθεια!

 

Μολις προεκυψε και προβλημα.:/

Τωρα 8ελω να κανω 1 λιστα απο λιστες αλλα μου πεταει παλι Segmentation.Καμια ιδεα πως να γινει η συνδεση χωρις να παιρνω Seg?

O λειτουργικος κωδικας ειναι ο εξης:

>#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main ( void )
       {
       char filename[]={0};
       int size;
       printf("Please give me the file's name:");
       scanf("%s", filename);
       FILE *file = fopen (filename, "r" );
       if ( file != NULL )
               {
               typedef struct node
                       {
                       char *filename;
                       int filesize;
                       struct node *next;
                       }List;
               List *root;
               root=malloc(sizeof(List));
               List* ptr=root;
               typedef struct cd
                       {
                       int current_size;
                       List * root;
                       struct cd * next;
                       }Cd;
               Cd * head;
               head=malloc(sizeof(Cd));
               Cd * prt=head;
               int grammh=1;
               char line [15]; /* or other suitable maximum line size */
               while (fgets ( line, sizeof line, file)!= NULL)
                       {
                       int x=0;
                       char str[] ={};
                       *str=*line;
                       char * pch;
                       pch = strtok (str," ");
                       char name[]={0};
                       while (pch != NULL)
                               {
                               if(x==0)
                                       {
                                       strcpy(name,pch);
                                       printf ("%s",name);
                                       pch = strtok (NULL, " ");
                                       x++;
                                       }
                               else
                                       {
                                       size=atoi(pch);
                                       printf("%5d\n",size);
                                       if(grammh<2)
                                               {
                                               if(size>=1000)
                                                       {
                                                       printf("!");
                                                       break;
                                                       }
                                               root->filename=name;
                                               root->filesize=size;
                                               root->next=NULL;
                                               while (root != NULL)
                                                       {
                                                       printf("%s %d\n",root->filename, root->filesize);
                                                       root = root->next;
                                                       }
                                               grammh++;
                                               }
                                       else
                                               {
                                               while(ptr->next!=NULL)
                                                       {
                                                       ptr=ptr->next;
                                                       }
                                               ptr->next=malloc(sizeof(List));
                                               ptr->next->filename=name;
                                               ptr->next->filesize=size;
                                               ptr->next->next=NULL;
                                               while (ptr->next!= NULL)
                                                       {
                                                       printf("%s %d\n",ptr->next->filename, ptr->next->filesize);
                                                       ptr= ptr->next;
                                                       }
                                               }
                                       pch = strtok (NULL, " ");
                                       x++;
                                       }
                               }
                       }
               fclose ( file );
               }
       else
               {
               perror ( filename );
               }
       return 0;
       }

O παραπανω κανει 1 λιστα.

Δημοσ.

Δεν είναι υποχρεωμένο, αλλά τα μοντέρνα λειτουργικά συστήματα το κάνουν έτσι κι αλλιώς (διαθέτουν συγκεκριμένη μνήμη στο κάθε πρόγραμμα, την οποία την ξαναπαίρνουν πίσω όταν τερματίσει το πρόγραμμα). Υπάρχουν όμως κι άλλες περιπτώσεις: http://en.wikipedia.org/wiki/Memory_leak.

 

Όταν θα βγει στο επάγγελμα και έχει μάθει να μη κάνει free() τη μνήμη που δεσμεύει, ανάλογα το επάγγελμα και την εφαρμογή, ενδέχεται να τα κάνει όλα μαντάρα και να μη βρίσκουν και τι φταίει (το άρθρο της Wikipedia είναι κατατοπιστικό). Επίσης, δεν ξέρω κατά πόσο στα embed systems και στα κινητά όπου κατά κόρον χρησιμοποιείται σήμερα η C γίνεται αυτόματα re-claim η user allocated μνήμη.

 

Σε γενικές γραμμές είναι ειλικρινά απορίας άξιο, αν όντως ο "καθηγητής" τους τους έχει πει πως δεν χρειάζεται να κάνουν free() (μου ακούγεται από αδιανόητο έως απαράδεκτο)!

 

Δεν θέλω να πω οτι κάνεις λάθος, περισσότερο να συμπληρώσω θέλω και να πω την άποψή μου.

Φυσικά και πρέπει να κάνουμε free() πάντα στο πρόγραμμα μας για να μην έχουμε memory leak για όσο τρέχει όμως. Προς θεού αυτό δε σημαίνει οτι μπορούμε να μην κάνουμε free αλλα πιστεύω το λειτουργικό σύστημα ΕΙΝΑΙ υποχρεωμένο να το κάνει μετά το τελος λειτουργίας του προγράμματος, για το αν αργεί η διαδικασία, υπεύθυνος είναι ο σχεδιαστής του λειτουργικού και όχι ο χρήστης του.

 

ΥΓ. Φίλε μου τα strings σου ακόμα δεν τα χεις φτιάξει (οπότε καλό ξε-μπέρδεμα με τα random segmentation faults :P )

Δημοσ.

Όταν γράφεις πέρα από την χωρητικότητα ενός string δεν ξέρεις πότε και που θα χτυπήσει run-time error, είναι random.

 

Φτιάξε τα strings σου, φτιάξε λίγο και τη δομή του προγράμματός σου (δομές έξω από τη main(), μεταβλητές συγκεντρωμένες πάνω-πάνω στη main(), άφηνε κάνα κενό ανάμεσα σε γραμμές λογικών ενοτήτων, κλπ) για να του ρίξω αν θες μια ματιά το βράδυ που θα πάω σπίτι.

 

Έτσι όπως είναι τώρα, εγώ τουλάχιστον δεν έχω κουράγιο καν να ξεκινήσω να το διαβάζω κανονικά (ενδεχομένως κάποιο άλλο παιδί όμως να μπορεί ;) )

Δημοσ.

Δεν νομιζω να κανω κατι τετοιο αλλα δεδομενου οτι το λες ετσι 8α ειναι! ^_^

Που συμβαινει αυτο γτ δε νομιζω να κανω κατι τετοιο.

Δημοσ.

Ούτε καν αυτό εδώ δεν θα έπρεπε να τρέχει!

 

>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main ( void )
{
char filename[]={0};
int size;
printf("Please give me the file's name:");
scanf("%s", filename);

puts("Eftasa edw kata tyxh. Pata ENTER gia termatismo");
fflush(stdin); getchar();

return 0;
}

Δημοσ.

Ούτε καν αυτό εδώ δεν θα έπρεπε να τρέχει!

 

>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main ( void )
{
char filename[]={0};
int size;
printf("Please give me the file's name:");
scanf("%s", filename);

puts("Eftasa edw kata tyxh. Pata ENTER gia termatismo");
fflush(stdin); getchar();

return 0;
}

Κι ομως στο Dev C++ δουλευει!Υποθετω και μεσω ssh client se unix.

Δημοσ.

Κατά τύχη! Και σε gcc δουλεύει, σε Pelles-C βαράει segmentation fault όμως (όπως έπρεπε να κάνει παντού, σύμφωνα με τα στανταρ της γλώσσας).

 

Over & out από μένα, αν νομίζεις πως καλώς βαίνεις έτσι όπως είναι ο κώδικάς σου, go ahead :P

 

ΥΓ. Δουλεύει γιατί κάνουν self-protect εκείνοι οι compilers

Δημοσ.

Κατά τύχη! Και σε gcc δουλεύει, σε Pelles-C βαράει segmentation fault όμως (όπως έπρεπε να κάνει παντού, σύμφωνα με τα στανταρ της γλώσσας).

 

Over & out από μένα, αν νομίζεις πως καλώς βαίνεις έτσι όπως είναι ο κώδικάς σου, go ahead :P

 

ΥΓ. Δουλεύει γιατί κάνουν self-protect εκείνοι οι compilers

 

Stack ειναι lifo, αρα απλα κανει ενα ελεγχομενο stack overflow, λογικα ειναι σε debug mode, αρα η main εχει μεγαλυτερο μεγεθος απο το κανονικο. Απλα γραφει προς τα πανω. πχ

post-216584-0-08762700-1306870938_thumb.jpg

 

 

Δημοσ.

Stack ειναι lifo, αρα απλα κανει ενα ελεγχομενο stack overflow, λογικα ειναι σε debug mode, αρα η main εχει μεγαλυτερο μεγεθος απο το κανονικο. Απλα γραφει προς τα πανω. πχ

post-216584-0-08762700-1306870938_thumb.jpg

Έχει να κάνει με την πλατφόρμα και τον compiler. Δυστυχώς δεν ακολουθούν όλοι τα στάνταρ για την εσωτερική υλοποίηση των string literals, χώρια ότι ακόμα και το ίδιο το standard (τουλάχιστον το ANSI) περιέχει ασάφειες.

 

Το αποτέλεσμα είναι, ορισμένοι compilers/πλατφόρμες να είναι πιο "ανθεκτικοί" σε... λαλακίες από άλλους αλλά και συγκριτικά με το στάνταρ (ή έστω αυτό που ήθελε να εννοήσει το standard :lol:).

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...