Programm bleibt hängen bei Werteeingabe für struct



  • Ein def_task benötigt 8 Byte. Das Problem hat sich allerdings gelöst, es lag nicht am Code an sich, dass es immernoch nicht funktionierte, sondern daran, dass ich zwischenzeitlich in einem anderen Ordner gearbeitet habe und Dev-C++ von da an beim Kompilieren automatisch die Files des anderen Ordners benutzt hat, meine Änderungen hat er also gar nicht berücksichtigt. Nach einem Neustart heute morgen sah die Welt dann ganz anders aus.

    Ich danke für die Hilfe


  • Mod

    Qlimaxer schrieb:

    Ein def_task benötigt 8 Byte.

    Naja. Zumindest unter der Annahme, dass int 4 Byte groß ist und kein Padding drin ist, mag das richtig sein. Muss aber nicht unbedingt so sein. Drück diese Größe doch lieber mal als ein sizeof aus. Und vergleich mal mit dem, was du genommen hast.



  • Das Problem hat sich überhaupt nicht gelöst, wenn du immernoch das da stehen hast:

    def_task *new_task = malloc(sizeof(def_task *));
    


  • Die Größe von 8 Byte habe ich bereits mittels sizeof ermittelt und ich habe doch auch sizeof bei jedem malloc-Aufruf benutzt!? Was ist denn der Fehler mit

    ? Wenn ich nur [code="c"]def_task *new task;
    

    mache funktioniert es nicht.



  • Habe scheinbar etwas mit den Code-Tags falsch gemacht. Die Frage war, was an der Zeile

    def_task *new_task = malloc(sizeof(def_task *))
    

    nicht stimmt.



  • Du möchstest doch die Größe des Strukts und nicht die Größe eines Zeigers auf die Struktur!
    Überlege dir wieso du da den Stern dran geschrieben hast.


  • Mod

    Die Größe von was willst du wissen und die Größe von was bestimmst du?

    Das mag gerade etwas verwirrend sein, da bei dir vermutlich beides den Wert 8 ergibt. Machen wir es mal etwas deutlicher:

    #include <stdio.h>
    struct Foo
    {
      char c[17];
    };
    
    int main()
    {
      printf("%u %u\n", sizeof(Foo), sizeof(Foo*));
      return 0;
    }
    

    https://ideone.com/Eb1oOJ



  • Ich verstehe worauf ihr hinaus wollt,

    def_task *new_task = malloc(sizeof(def_task));
    

    wäre richtig, nicht wahr? Das hatte ich sogar schon geändert, aber es kommt tatsächlich zum gleichen Ergebnis wenn ich es mit * schreibe.

    Die aktuelle Version sieht so aus:

    void enqueue(def_task* queue, int id, int length){
    
    	def_task *new_task = malloc(sizeof(def_task ));
    	if (new_task == NULL){
    		printf("Error while allocating memory..\n");
    		return;
    	}
    	new_task->id = id;
    	new_task->length = length;
    	size++;
    
    	def_task *tmpqueue = malloc(size * sizeof(def_task));
    
    	int i;
    	for (i=0; i<(size-1); i++) tmpqueue[i] = queue[i];
    
    	tmpqueue[size-1] = *new_task;
    	queue = malloc(size * sizeof(def_task));
    
    	for (i=0; i<size; i++) queue[i] = tmpqueue[i];
    	return;
    }
    
    def_task* dequeue(def_task *queue){
    	def_task *task = queue;
    	printf("%d", size);
    	if(size >= 2){
    		size--;
    		queue = (def_task *)realloc(&queue[1], (size) * sizeof(def_task));
    	}
    
    	else{
    		size = 0;
    		queue = malloc(0);	
    	}
    	return task;
    }
    

    Aber auch das tut nicht das was es soll, wenn ich das erste Element der queue aufrufen möchte, bekomme ich das zuletzt hinzugefügte, was nun nicht im Sinne einer Queue ist.


  • Mod

    Könntest du etwas vollständiger erklären, was das Programm machen soll, was du erwartest, was stattdessen passiert?
    Siehe:
    http://www.c-plusplus.net/forum/304133

    Was mir auffällt:
    Zeilen 12-20 sind total umständlich. Du könntest doch auch der queue einfach den neuen Wert vom tmpqueue zuweisen, anstatt alles 2x zu kopieren und dir somit eine Kopie sparen. Oder besser: Du nutzt realloc, welches du ja offensichtlich kennst, und sparst dir somit ggf. sogar alle Kopien (und die, die nötig sind, erfolgen dann automatisch durch das realloc).

    Weiterhin hast du riesige Speicherlöcher. Du malloc'st zwar viel, aber free'st nirgends, bevor du die Zeiger wegwirfst.

    Beim ersten malloc prüfst du noch auf Erfolg. Wenn du dies für nötig hälst, wieso dann nicht bei den viel kritischeren späteren mallocs?

    Manchmal castest du den Rückgabewert von (re/m)alloc (in C unnötig), manchmal nicht. Warum?

    Was erhoffst du dir von einem malloc(0) ?

    Zeile 31 sieht nach totalem Unsinn aus. Keine Ahnung, was du da machen willst. Du weißt, dass Feldindizes bei 0 anfangen? Oder soll das, das Feld vorne um 1 verkürzen? Ich glaube, du weißt doch nicht, was realloc macht. Schlag mal nochmal nach, was es eigentlich tut. Es verschiebt jedenfalls keine gemallocten Zeiger an eine andere Stelle deiner Wahl.

    Der Code sieht so aus, als wäre er von 5 verschiedenen Personen geschrieben worden. Trifft es das in etwa? Hast du einfach Codefetzen aus dem Internet zusammenkopiert/abgeschrieben?

    c.rackwitz schrieb:

    Wenn du selber Code schreibst, musst du ihn auch verstehen. Code ist kein Haufen von wahllos zusammengeschmissenen Buchstaben und Zeichen, Code ist Logik pur. Du musst genau wissen, warum du wo und welches Zeichen setzt.

    Das gilt ganz besonders bei manueller Speicherverwaltung. Jeder Fehler im Code führt hier entweder zu brutalen Abstürzen oder zu ganz subtilem Fehlverhalten, welches im schlimmsten Fall unbemerkt bleibt, aber falsche/unzuverlässige Ergebnisse produziert und in allen Fällen sind die Fehler schwer zu finden. Wenn du nicht weißt, wie manuelle Speicherverwaltung in C funktioniert, dann lies es nach.



  • Der Code ist aussschließlich von mir aber ich verstehe wie du zu der Annahme kommst. Wie gesagt ist das für mich seit langem wieder der erste Versuch mit C. Ich hatte die Zeilen 12-20 auch schon durch ein realloc ersetzt, diese umständliche Variante habe ich für mich selbst gewählt um genauer zu verstehen was dabei passiert.

    Dass ich an einigen Stellen caste und an anderen nicht liegt schlicht daran, dass ich programmiere während ich Tutorials und ähnliches lese und manche Autoren in ihrem Beispielcode casten und manche nicht. Also danke für den Hinweis, dass das bei C unnötig ist.

    malloc(0) soll wohl das gleiche machen wie free(), wie ich gehört habe, bin jetzt beim Recherchieren aber zu dem Schluss gekommen dass das nicht stimmt. free() habe ich einfach vergessen zu benutzen -.-

    Und ja ich hatte vor das Feld vorne um 1 zu verkürzen, schade dass das nicht geht.

    Das Programm soll im Großen und Ganzen eine Art Modellierung verschiedener Scheduling-Verfahren sein. Als ankommende tasks benutzen wir das struct:

    typedef struct task_s
    {
    	int id;
    	int length;
    } def_task;
    

    Dafür benötigt man natürlich dann auch eine Queue von Tasks, die vor allem eben die Funktionalitäten enqueue und dequeue bieten muss.


  • Mod

    Eine übliche, effiziente und vergleichsweise einfache Implementierung einer Queue in C ist ein (dynamisches) Array, welches man in Form eines Ringpuffers benutzt. So vermeidet man teure Verschiebungen. Man merkt sich dazu: Größe des Feldes, Beginn der Queue, Ende der Queue. Beim Entfernen wandert der Anfang eine Position weiter. Beim Einfügen wandert das Ende eine Position weiter. Dabei muss das Feld ggf. vergrößert werden, wenn zwischen Ende und Anfang kein Platz mehr ist. Bei allen diesen Aktionen werden die Positionszeiger natürlich ggf. am Ende des Feldes passend umgebrochen.


Anmelden zum Antworten