Untypischer Laufzeitfehler durch malloc()



  • @EL-europ
    😵 Mein Fehler. hab -lncurses vergessen. programm lässt sich fehlerfrei compilieren



  • @firefly Ja, genau. Danke



  • @Swordfish
    mit "#if defined var" fragt der Präprozessor wo genau nach ob die Variable var gesetzt ist?
    mit "#pragma com(lib, 'str')" werden Compileroptionen gesetzt. Welche Bedeutung haben com, lib und str
    mit "#define Sleep..." wird Sleep(x) durch usleep((x) * 10000) ersetzt. Gibt es in win eine Funktion namens "Sleep(int x)"? oder wie funktioniert das delay bei compilierung auf win?

    Bei der Analyse hab ich curses ausgelassen, das ist ein eigenes Thema denke ich, und komme zu folgendem Ergebnis.
    Dein Code scheint Objektorientiert zu sein?
    ich hab vergessen den Speicher wieder frei zu geben☠

    Bezüglich enum:
    Der mir ersichtliche Vorteil ist das ich sie im Editor "zusammenklappen" kann.
    Jürgen Wolf schreibt das Enumerationen mit Bezeichner, im Gegensatz zu #define vom Debugger symbolisch dargestellt werden!
    Was meint er damit?

    bezüglich size_t in snake_t.lenght und snake_t.new_lenght
    was ist hier der Unterschied zu int, oder warum benutzt du size_t statt int?

    Was mir hier unbedeutend ist (curses) aber dich vielleicht interessiert
    Das Resize des Terminal funktioniert bei mir nicht
    Wenn ich curses nicht initialisiere und dem restlichen code nach "if(resizeterm.." auskommentiere,
    funktioniert die Ausgabe das das Terminal nicht resized werden konnte.
    Wenn ich das komplette Programm mit werten die zu resize führen aufrufe, wird nicht resized,
    das Spiel startet, aber was über rechts hinausgeht zeichnet er dann am linken Rand weiter.



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    mit "#if defined var" fragt der Präprozessor wo genau nach ob die Variable var gesetzt ist?

    Der Präprozessor kennt keine in C deklarierten Variablen. defined _MSC_VER gibt 1 wenn das Präprozessorsymbol _MSC_VER definiert wurde. Das ist der Fall wenn mit dem Microsoft C++-Compiler übersetzt wird.

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    mit "#pragma com(lib, 'str')" werden Compileroptionen gesetzt. Welche Bedeutung haben com, lib und str

    https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-160

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    mit "#define Sleep..." wird Sleep(x) durch usleep((x) * 10000) ersetzt. Gibt es in win eine Funktion namens "Sleep(int x)"?

    Genau. Und ja.

    https://docs.microsoft.com/de-de/windows/win32/api/synchapi/nf-synchapi-sleep

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    Bezüglich enum:
    Der mir ersichtliche Vorteil ist das ich sie im Editor "zusammenklappen" kann.
    Jürgen Wolf schreibt das Enumerationen mit Bezeichner, im Gegensatz zu #define vom Debugger symbolisch dargestellt werden!
    Was meint er damit?

    Erster Beweggrund ist Namen zu haben anstatt im ganzen Code Magic Numbers zu verteilen. Zweitens hat man dadurch auch einen Typ der dabei hilft zu dokumentieren welche Werte (bzw. symbolische Konstanten) für welche Variablen sinnvoll sind. Was Wolf meint? Wahrscheinlich daß man eben statt den Zahlen einen Bezeichner sieht.

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    bezüglich size_t in snake_t.lenght und snake_t.new_lenght
    was ist hier der Unterschied zu int, oder warum benutzt du size_t statt int?

    Für size_t ist garantiert daß der Typ groß genug für jedes mögliche Objekt im Speicher ist.

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    Was mir hier unbedeutend ist (curses) aber dich vielleicht interessiert
    Das Resize des Terminal funktioniert bei mir nicht

    Ja, bei mir auch nicht. Hab' es mit (u)rxvt und xterm probiert.

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    Dein Code scheint Objektorientiert zu sein?

    Bingo. Mir hätte zwar die Erkenntnis gereicht daß ich ohne globale Variablen auskomme und jede Funktion eine klare Aufgabe hat, aber ... 🙂
    Siehst Du die Vorteile?



  • @Swordfish
    Also kann ich mit "if defined" nur Eigenschaften des eingesetzten Compilers abfragen?
    Ja, ich glaube du hast alles was geht in Funktionen ausgelagert
    Für mich als Anfänger wird der Code dadurch schwerer lesbar, aber ich will ja was lernen und habe den Autor an der Seite. Ich bin den Code Zeile für Zeile durch gegangen, aber weshalb der komplette body gezeichnet wird kann ich noch nicht nachvollziehen. Da ist mir dann die Luft ausgegangen nach dem ich alle anderen zurückgestellten Fragen (ausser curses) geklärt habe 🙂
    Danke das du dir die Mühe gemacht hast und einen kompletten Code zum Nachvollziehen geschrieben hast. Das hilft mir sehr



  • @Swordfish
    Ich muss mich korrigieren
    Dein Code ist viel lesbarer als meiner. Ohne die Kommentare würde mein Code völlig unleserlich sein, man bräuchte Notizen und müsste sich viel mehr im Gedächtnis behalten; deiner ist auch ohne Kommentare lesbar. Vielleicht schwierig als Anfänger wegen den vielen Funktionen, aber ohne Kommentare, Notizen usw... lesbar



  • @Swordfish
    Ach, eine Frage hab ich vergessen:

    for (size_t i = snake->length - 1; i; --i)
    

    Weshalb funktioniert diese Schleife obgleich die Abbruchbedingung lediglich die Zählvariable 'i' ist?



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    Weshalb funktioniert diese Schleife obgleich die Abbruchbedingung lediglich die Zählvariable 'i' ist?

    Der mittlere Ausdruck einer for Schleife wird als Bedingung ausgewertet. Die Regel dabei ist dass 0 als false gilt und alle anderen Werte als true.

    D.h. i als Laufbedingung ist gleichbedeutend mit i != 0.

    Das selbe gilt z.B. auch in if Statements. Also if (i) ist gleichbedeutend mit if (i != 0). Bei Zeigern hast du das vermutlich schon gesehen, da schreibt man gerne nur if (pointer) statt if (pointer != 0) oder if (pointer != NULL).

    Bei Integers finde ich persönlich es aber komisch. Kann man machen wenn 0 für "nichts" steht, z.B. wenn man in einem Integer einzelne Bits als Flags für etwas verwenden und dann mit if (flags) prüft ob irgend ein Flag gesetzt ist - da finde ich es noch OK. Wenn 0 aber einfach nur für die Zahl 0 steht wie in diesem Beispiel, würde ich eher i != 0 schreiben.

    ps: Ganz furchtbar finde ich if (strcmp(a, b)). Diese Bedindung ist wahr wenn strcmp(a, b) etwas anderes als 0 zurückgibt, und das tut sie wenn die Strings unterschiedlich sind. Da kann man sich beim schnell drüberlesen leicht vertun und fälschlicherweise annehmen dass der Block betreten wird wenn die Strings gleich sind.



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    @Swordfish
    Also kann ich mit "if defined" nur Eigenschaften des eingesetzten Compilers abfragen?

    Der C Präprozessor überprüft damit nur, ob eine Variable des Präprozessors definiert wurde. Beispiel

    #include <stdio.h>
    #include <stdlib.h>
    
    int main () {
    #ifdef LINUX
        printf("Linux\n");
    #else
        printf("anything else\n");
    #endif
    
        return EXIT_SUCCESS;
    }
    

    #ifdef ist die Kurzform von #if defined. Man kann auf der Kommandozeile beim Übersetzen mit dem gcc "-D" + "NAME" angeben, so dass die Variable definiert wird: gcc -DLINUX example.c -o example übersetzt den Code in der einen Variante und ohne in der anderen.



  • @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    Ohne die Kommentare würde mein Code völlig unleserlich sein, man bräuchte Notizen und müsste sich viel mehr im Gedächtnis behalten;

    Dann weißt Du jetzt ja warum ich

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    Aber Ich glaube die curses kommt mit schnellen Tastenanschlägen nicht so klar. wenn ich im "Automove-modus" eine Zeit (ca. 3-5min) lang spiele, stürzt das Programm einfach ab. Kannst du mir nochmal Helfen?

    nicht beantworten wollte ^^



  • @john-0
    Das Funktioniert so wie du schreibst. Doch in dem Übungsprogramm
    steht '#if defined MSC_VER ... #elif defined linux' und ich hab kein -D__linux_ beim kompilieren gesetzt. Aber er hat den Code nach linux eingesetzt. Gibt es irgend eine Datei in welcher der Präprozässor standardmäßig Variablen wie z.B. _MSC_VER oder linux abfragt oder hat er die "in sich"? er muss ja irgendwo linux bei mir gefunden haben, sonst hätte der Aufruf der Sleep-Funktion beim compilieren einen Fehler ausgelöst.



  • @Swordfish
    Ja, beim lernen von c tun sich bei mir mehrere Baustellen gleichzeitig auf. Ist ne ganz andre Sache als python. Der Compiler hat wohl fast den gleichen Einfluss wie der Code.
    Eine Bitte habe ich noch. Erklär mir bitte diesen Schleifenkopf aus deinem Programm

    for (size_t i = snake->length - 1; i; --i)
    

    Hier ist doch die Abbruchbedingung gleich der Zählvariable, wieso Funktioniert die Schleife?



  • @EL-europ Denk dir an der Stelle ein i != 0
    dann solltest du darauf kommen.

    Mehr steht bei https://www.c-plusplus.net/forum/topic/352442/untypischer-laufzeitfehler-durch-malloc/56



  • @DirkB
    Bedeutet das jetzt das der Compiler von alleine versteht das hier "i != 0" gemeint ist, und man immer einfach die Zählvariable schreiben kann wenn man "Zählvariable != 0" meint?


  • Mod

    @EL-europ sagte in Untypischer Laufzeitfehler durch malloc():

    @DirkB
    Bedeutet das jetzt das der Compiler von alleine versteht das hier "i != 0" gemeint ist, und man immer einfach die Zählvariable schreiben kann wenn man "Zählvariable != 0" meint?

    Ja. Siehe auch ein anderer kürzlicher Beitrag von dir zum Thema if (filestream). Wobei diese Schreibweise aber ungewöhnlich ist um Integervariablen auf Gleichheit mit 0 zu vergleichen, würde ich in einem Codereview ankreiden. Besonders wenn der autor nicht einmal selber weiß, warum es das macht.



  • @SeppJ
    Danke für die Antwort. Als Neuling in c ist solch ein Schleifenkopf fragwürdig. Da liest man schon gerne das er solch eine "Gültigkeit" hat



  • @EL-europ i != 0 ist ein sog. Ausdruck. Eine Berechnung, die ein Ergebnis liefert.
    In diesem Fall eine 1 (für wahr), wenn i ungleich 0 ist und
    0 (für unwahr), wenn i gleich 0 ist.

    In C gilt 0 als unwahr, alles andere als wahr.

    i ist auch ein Ausdruck und liefert den Wert von i

    Ein Funktionsaufruf liefert auch einen Wert. (sofern die Funktion einen Rückgabewert hat)





  • @SeppJ sagte in Untypischer Laufzeitfehler durch malloc():

    Wobei diese Schreibweise aber ungewöhnlich ist um Integervariablen auf Gleichheit mit 0 zu vergleichen, würde ich in einem Codereview ankreiden.

    Ich verstehe ehrlichgesagt nicht warum es so ungewöhnlich sein soll. Jemandem der die Sprache versteht ist die Bedeutung doch sofort klar.



  • @Swordfish Ich schätze mal dass es ungewöhnlich ist weil es sich für die meisten Leute komisch anfühlt.
    if (flags) fühlt sich OK an.
    if (number_of_elements) fühlt sich auch noch OK an.
    if (x_coordinate) fühlt sich komisch an.
    Und if (index) fühlt sich für mich halt auch komisch an. Speziell wenn es in einer Schleife auftaucht die von N-1 bis 1 laufen soll. Weil allein das schon ungewöhnlich ist. Die meisten Schleifen laufen halt von 0 bis N-1, ein paar wenige von N-1 bis 0, aber extrem wenige von N-1 bis 1.