Verrücktes malloc Problem



  • Hallo!

    Also ich habe mir so eine Art dynamische Liste geschrieben, die ähnlich einer Hashtable funktioniert.
    Werte(Strings) werden hinten eingetragen, fall sie bereits vorhanden sind wird anz inkrementiert.

    Typ:

    struct twort {
      string wort;
      int anz;
      struct twort* next;
    };
    

    Code:

    int zaehleWort (string wort) {
      struct twort* hilf = wortliste;
      int ende=0; /*0..kein Ende, 1..Gefunden, 2..Nicht Gefunden*/
      /*Liste durchlaufen und ueberpruefen*/
      if (hilf!=0) {
        while(ende==0) {
          /*Wort schon eingetragen=>anz erhoehen und Schleife verlassen*/
          if (hilf->wort==wort) {
            hilf->anz++;
            ende=1;
          /*Wort nicht gefunden, also weiterschauen*/
          } else {
            if (hilf->next==0) {
              ende=2;
            } else {
              hilf=hilf->next;
            }
          }
        }
      /*Liste wird angelegt*/
      } else {
        struct twort* neu = (struct twort*)malloc(sizeof(struct twort));
        neu->wort=wort;
        neu->anz=1;
        neu->next=0;
        wortliste=neu;
        ende=1;
      }
    
      /*Wurde das Wort nicht gefunden, wird es eingetragen*/
      if (ende==2) {
        struct twort* neu = (struct twort*)malloc(sizeof(struct twort));
        neu->wort=wort;
        neu->anz=1;
        neu->next=0;
        hilf->next=neu;
      }
      return 0;
    }
    

    Und hier tritt immer der Absturz mit Windowsfehlermeldung auf und ich verstehe einfach nicht warum. (Siehe Kommentar im Quelltext)

    if (ende==2) {
        struct twort* neu = (struct twort*)malloc(sizeof(struct twort));
    /*Hier tritt der Fehler auf obwohl neu sicher den Speicher bekommen hat!!*/
        neu->wort=wort;
        neu->anz=1;
        neu->next=0;
        hilf->next=neu;
      }
    

    Ok danke schon mal an alle und ich hoffe jemand kann mir helfen!

    Mfg Harald



  • Welche Fehlermeldung gab es denn? Hast du überprüft, ob die struct nachher auf NULL zeigt? (Das zeigt einen Fehler an)

    Noch nen Tip, wo wir hier in C++ sind: du kannst auch die STL-Listen verwenden, spart viel Arbeit und Ärger 😉



  • voidpointer schrieb:

    ...
    Noch nen Tip, wo wir hier in C++ sind: du kannst auch die STL-Listen verwenden, ...

    ... und new/new[]/delete/delete[]

    Gruß,

    Simon2.



  • voidpointer schrieb:

    Noch nen Tip, wo wir hier in C++ sind:...

    und in C++ bitte nur malloc verwenden wenn du einen wirklich guten Grund dafür hast (und dir die Konsequenzen bekannt sind).

    cu André



  • Simon2 schrieb:

    voidpointer schrieb:

    ...
    Noch nen Tip, wo wir hier in C++ sind: du kannst auch die STL-Listen verwenden, ...

    ... und new/new[]/delete/delete[]

    Scott Meyers konnte mich davon überzeugen, sowas gar nicht mehr zu verwenden. Ich bin vollkommen auf std::tr1::shared_ptr umgesattelt und habe mir für den einfachen Fall, in dem es sich um einen lokalen Zeiger handelt, der nie kopiert wird, eine separate Klasse geschrieben, die die Deleter-Semantik von shared_ptr emuliert (bin mir noch nicht ganz sicher, ob das so klappt, wegen der Type Erasure).

    Langer Rede kurzer Sinn: Dont. Ever. Use. delete .



  • ehm ja ok also ist malloc schon mal schlecht, aber mich würde interessieren wo hier der Fehler ist, wieso einmal das anlegen klappt und das nächste mal nicht? malloc macht doch an sich keine probleme mit c++ kompiler oder?



  • ne, das is auch quatsch, dass man nicht malloc() nutzen sollte... 😛 mache ich jeden tag...

    das geht schon aber oft übersieht man halt was...
    was is es denn nun für ein fehler? speicherzugriffsfehler oder beschaffungsfehler?



  • voidpointer schrieb:

    ne, das is auch quatsch, dass man nicht malloc() nutzen sollte... 😛 mache ich jeden tag...

    Das eine hat mit dem anderen aber nichts zu tun. Nur weil Du es machst heißt das noch nicht, dass es toll ist. In C hat man halt keine guten Alternativen. Unter C++ ist es unnötig gefährlich.



  • hm naja der streit um malloc oder nicht, das ist halt ansichstsache! ich bin auch für malloc, aber egal, da könnte man jetzt auch gleich über cout und printf streiten...

    aber zum problem, malloc kann den speicher reservieren, trotzdem die fehlermeldung...



  • HE schrieb:

    hm naja der streit um malloc oder nicht, das ist halt ansichstsache!

    nee, ist es nicht. malloc in c++ ist einfach falsch. und gefährlich.



  • ok ok wenn wir schon dabei sind, wie wäre es mal mit argumenten?!?!?!?!?!



  • Soweit ich weiß, reserviert dir malloc einfach das, was du angefordert hast und gibt einen Pointer zurück - Ohne jegliche Konstruktoraufrufe, oder wenigstens den Speicherbereich sinnvoll zu füllen.

    Ist wahrscheinlich nur halbwissen, aber der fehlende Konstruktoraufruf sollte schon das K.O. für malloc in C++ sein.



  • malloc reserviert zwar Speicher, ruft im Gegensatz zu new aber keine Konstruktoren auf. free gibt den Speicher wieder frei, ruft im Gegensatz zu delete aber keine Destruktoren auf.
    Bei den eingebauten Datentypen char, int, double, etc. spielt das vielleicht keine Rolle, aber jedem Anfänger sollte klar sein, dass sich malloc nicht mit Objekten verträgt.



  • na klar da habt ihr recht, wenn man mit objekten arbeitet ist malloc sicher nicht das nullplusultra, allerdings muss ich nur speicher für ein struct reservieren und dazu reicht malloc allemal.



  • was sagt die fehlermeldung denn genau? kannst du es hier hin schreiben oder vllt nen screenshot? möglicherweise nen speicherzugriffsfehler, der schon weiter vorne im programm verursacht wurde?

    wichtig ist auch, zu wissen, wo genau der fehler auftrat... (debugger?)

    neu->next=0;
    

    solltest du vllt besser umschreiben als

    neu->next=NULL;
    

    Das macht deinen Code C-Portabel und lesbarer 👍



  • Ehm du weißt aber, das eine struct nicht wirklich was anderes ist wie eine class? Hmm ... gut ... und warum sollte man nicht die Funktionen des C++-Standards nutzen, sondern die des C-Standards, um ein Programm in C++ zu schreiben? ?



  • voidpointer schrieb:

    solltest du vllt besser umschreiben als

    neu->next=NULL;
    

    Das macht deinen Code C-Portabel und lesbarer 👍

    Und verleitet zu fehlerhaften Annahmen in einen Fall wenn man mit überladenen Methoden arbeitet, wo eine ein int, und eine andere einen Zeiger erwartet... NULL ist 0 (in Zukunft, sprich C++0x umgeht man dies hoffentlich mittels null_ptr). Wenn man C-Portabel schreiben will sollte man imho ganz auf C++ verzichten. Ansonsten schaut man vielleicht bei Schnittstellen die C-binärkompatibel sind darauf, aber ansonsten ist das meines erachtens falsch.

    Wenn er C programmieren will soll er in das C-Unterforum gehen. C++ zumindest ist nicht C und man braucht auch eine rein C-Portable Syntax nur in seltenen Fällen.

    cu André



  • Hmm mal kurz nen bissel kürzen hier:

    void cound_words(std::string const& word) 
    {
    	if (list_words == NULL) { list_words = new word_t(word); return; }
    
    	word_t* last(list_words);
    	for (word_t* cur(list_words); cur != NULL; cur = cur->next) 
    	{
    		if ((*cur).word == word) 
    		{
    			++(*cur).count;
    			return;
    		}
    		last = cur;
    	}
    
    	last->next = new word_t(word);
    }
    

    ... so bekommst du das doch schön kurz & knackig 😛

    Voraussetzung dafür ist allerdings ne Struktur ordentlich einzusetzen:

    struct word_t
    {
    	std::string word;
    	word_t*		next;
    	std::size_t	count;
    	word_t(std::string const& word) : word(word), next(NULL), count(1) {}
    };
    


  • null_ptr wird echt praktisch. Ich hab mir mal ein Ersatz-Template gebastelt das ungefähr so aussah:

    namespace dons
    {
    	template <class T>
    	T* null_ptr(T*)
    	{
    		return 0;
    	}
    }
    

    Damit konnte man dann sowas machen:

    using dons::null_ptr;
    
    int*  p1 = null_ptr(p1);
    char* p2 = null_ptr(p2);
    
    int i1 = null_ptr(i1); // Fehler
    int i2 = null_ptr(p1); // Fehler
    

    Der Parameter ist ziemlich unschön, aber war ja eh nur mal so zum Spass. 😃

    Gruß
    Don06



  • ja eigentlich besteht das programm hauptsächlich aus code der mit einem c kompiler kompiliert werden könnte, allerdings bietet c++ einige Möglichkeiten, welche in c nur sehr schwer zu verwirklichen sind. deshalb schien mir c++ die bessere wahl, da es ja nicht verboten ist in c++ objektlos zu programmieren. ich könnte mir schon vorstellen in einem späteren moment das ganze auf c umzuschreiben, aber egal...!

    Wenn er C programmieren will soll er in das C-Unterforum gehen. C++ zumindest ist nicht C und man braucht auch eine rein C-Portable Syntax nur in seltenen Fällen.

    Jepp ich tat mich bei der wahl nicht leicht, ich nahm allerdings dann dieses unterforum, weil ich erstens einen c++ compiler verwende und zweitens im c forum wahrscheinlich nur wegen meiner strings verurteilt würde.

    neu->next=NULL

    naja wegen NULL oder 0 lässt sich streiten. NULL bedeutet ja nichts anders als die Speicheradresse 0 oder 0x00, aber ihr habt schon recht, besser verständlich wäre NULL. sorry

    Problemsignatur:
    AppName: program.exe
    AppVer: 0.0.0.0
    ModName: program.exe
    ModVer: 0.0.0.0
    Offset: 00009669

    Problemberichtinhalt:
    Code: 0xc0000005
    Flags: 0x00000000
    Record 0x0000000000000000
    Address:0x0000000000409669

    Kein Ahnung was euch da noch helfen könnte!

    Danke für die bisherigen Antworten



  • Oh großen Dank an (D)Evil für deine Hilfe!

    Ich glaube ich werde wohl meine C-passion fallen lassen müssen und follends der Objektivität von c++ mich zuwenden. Ich denke das löst mein Problem.

    Danke vielmals du hast mir sehr geholfen!
    Danke an alle!


Anmelden zum Antworten