bGeissl Geschrieben 28. Mai 2008 Geschrieben 28. Mai 2008 Hallo, :new: und ich habe ein Problem mit einer C-Funktion. Ich möchte eine Trim-Funktion selber schreiben. Die wird es vielleicht schon in string.h geben, ist mir aber egal. Hier erstmal der C-Code: char *trim(char *expression){ printf("1: %ld\n", expression); while (*expression == ' '){ expression++; } printf("2: %ld\n", expression); char *j = expression; while (*expression != 0){ expression++; } if (j != expression) expression--; printf("3: %ld\n",i); printf("4: %ld\n",expression); printf("5: '%c'\n",*expression); printf("6: %ld\n",*expression); while (*expression == ' '){ printf("7: %ld\n",expression); printf("8: '%c'\n",*expression); printf("9: %ld\n",*expression); //Hier der Absturz... *expression = 0; expression--; } return j; } Warum stürzt das Programm in der Zeile "*expression = 0" ab? Ich krieg die blöde Trim-Funktion einfach nicht hin. Der Aufruf printf("Ergebnis: '%s'\n", trim(&" A B c "[0])); druckt entweder 'A B c ' statt 'A B c' oder alles stürzt ab. Ich habe daraufhin das bloodsheed Dev C++ nochmal installiert. Der Fehler kam trotzdem wieder. Dann habe ich MinGW 5.1.4 vom 26. April 2008 installiert und im Dev-C++-Editor/Debugger alle Pfade angepasst. Nichts ändert sich. Dann habe ich MS Visual C++ 2008 Express installiert. Das sagt an der selben Stelle sowas wie: Unbehandelte Ausnahme bei 0x0041199a in ZweiterTest.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x00416789. Hat jemand eine Idee, wie es weiter gehen könnte? Gruß bGeissl Zitieren
Klotzkopp Geschrieben 28. Mai 2008 Geschrieben 28. Mai 2008 Du übergibst ein Stringliteral an deine Funktion. Auf Stringliterale darfst du aber nicht schreibend zugreifen. Zitieren
bGeissl Geschrieben 28. Mai 2008 Autor Geschrieben 28. Mai 2008 Wenn ich erst eine Variable anlege und dann die Funktion aufrufe, klappt es! char test[255] = " A B C "; printf( "Trim: '%s'\n", trim(test)); Danke! Zitieren
Guybrush Threepwood Geschrieben 28. Mai 2008 Geschrieben 28. Mai 2008 Dir sollte aber bewusst sein das dadurch das du einfach den übergebenen Zeiger umsetzt es Probleme gibt sobald der Speicher zur Laufzeit reserviert wurde und nach dem Trim Aufruf wieder freigeben werden soll. Zitieren
bGeissl Geschrieben 28. Mai 2008 Autor Geschrieben 28. Mai 2008 ...wie soll dann deiner Meinung nach die Funktion aussehen? So...? char *trim(char *expression){ char *i = expression; //So...? while (*expression == ' '){ expression++; } char *j = expression; while (*expression != 0){ expression++; } if (j != expression) expression--; while (*expression == ' '){ *expression = 0; expression--; } expression = i; //...und so? return j; } Zitieren
Guybrush Threepwood Geschrieben 28. Mai 2008 Geschrieben 28. Mai 2008 Nein das ist ja im Prinzip das Selbe. Du müsstest die Zeichen eigentlich umkopieren so dass dein Zeiger immer noch an die Selbe Stelle zeigt, da nur was anderes steht. Ich bin mir jetzt nicht sicher ob dabei eine Exception auftritt oder einfach nur ein Speicherleck ohne das man es merkt und kann es gerade nicht ausprobieren. Aber ruf deine trim Funktion mal so auf: char *string = malloc(12 * sizeof(char)); strcpy(string," Hallo "); string = trim(string); delete string; [/PHP] Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 string = trim(string);So was macht man ja auch nicht delete string;Malloc und delete? Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 So was macht man ja auch nicht Wieso nicht? Ich würds tun Malloc und delete? Oh sorry muss natürlich free(string); heißen Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Wieso nicht? Ich würds tun Hast du häufiger Probleme mit Speicherlecks? Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Nein ich programmier ja kein C oder C++ Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Die Zuweisung an string ist problematisch, weil du damit den Zeiger, der auf von dir angeforderten dynamischen Speicher zeigt, überschreibst. Damit hast du keine Möglichkeit mehr, den Speicher wieder freizugeben -> Speicherleck. Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Genau das hab ich ja oben geschrieben Dir sollte aber bewusst sein das dadurch das du einfach den übergebenen Zeiger umsetzt es Probleme gibt sobald der Speicher zur Laufzeit reserviert wurde und nach dem Trim Aufruf wieder freigeben werden soll. Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Genau das hab ich ja oben geschrieben Nicht so ganz. Das Problem liegt nicht in bGeissls Funktion, sondern darin, wie du sie benutzt. Der übergebene Zeiger wird ja nur in der Funktion geändert. Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Naja das ist jetzt Geschmackssache. Ob man jetzt sagt die Funktion arbeit so das du sie beliebig aufrufen kannst oder so das man sie nur nach ganz bestimmten Regeln aufrufen darf. So oder so gibts Probleme wenn man es wie beschrieben verwendet und das war alles auf das ich hingeiwesen habe Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Naja das ist jetzt Geschmackssache. Ob man jetzt sagt die Funktion arbeit so das du sie beliebig aufrufen kannst oder so das man sie nur nach ganz bestimmten Regeln aufrufen darf.Man darf die Funktion beliebig aufrufen. Das Problem liegt doch allein in der Zuweisung, die du nach dem Aufruf machst. Dieser Code läuft ohne Probleme: char *string = malloc(12 * sizeof(char)); strcpy(string," Hallo "); char* foo = trim(string); free string; [/code] (Mit der Einschränkung, dass man foo nicht mehr benutzen darf, wenn string nicht mehr da ist, aber das halte ich für unproblematisch.) So oder so gibts Probleme wenn man es wie beschrieben verwendet und das war alles auf das ich hingeiwesen habe So, wie du das benutzt, gibt es mit [i]jeder [/i]Funktion Probleme, die nicht den Parameter free-t und den Rückgabewert malloc-t, was IMHO ein sehr ungewöhnliches Verhalten für Funktionen wäre. Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 (bearbeitet) Man darf die Funktion beliebig aufrufen. Das Problem liegt doch allein in der Zuweisung, die du nach dem Aufruf machst. Ja natürlich liegt es daran aber wenn man es anders aufruft muss ggf. extra eine zusätzliche Variable für das Ergebnis anlegen. So, wie du das benutzt, gibt es mit jeder Funktion Probleme, die nicht den Parameter free-t und den Rückgabewert malloc-t, was IMHO ein sehr ungewöhnliches Verhalten für Funktionen wäre. Nein Probleme gibt es mit jeder Funktion die den Ursprungszeiger umbiegt. Edit: Wobei das natürlich auf der anderen Seite bedeuten würde das man den übergebenen String verändert und keine Version mehr mit Leerzeichen am Anfang hätte, was wahrscheinlich auch nicht so schick ist. Bearbeitet 29. Mai 2008 von Guybrush Threepwood Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Nein Probleme gibt es mit jeder Funktion die den Ursprungszeiger umbiegt. Die Funktion biegt nichts um. C ist Call-By-Value. Der Funktionsaufruf ändert den Zeiger string nicht. Zitieren
bGeissl Geschrieben 29. Mai 2008 Autor Geschrieben 29. Mai 2008 So isses: char test[255] = " A B C "; printf( "Addr1: %ld\n", test); printf( "Trim: '%s'\n", trim(test)); printf( "Addr2: %ld\n", test); ...ergibt... Addr1: 2292320 Trim: 'A B C' Addr2: 2292320 Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Die Funktion biegt nichts um. C ist Call-By-Value. Der Funktionsaufruf ändert den Zeiger string nicht. Umbiegt und zurückgibt natürlich... Zitieren
Klotzkopp Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Umbiegt und zurückgibt natürlich...Dann hat also deiner Meinung nach jede Funktion, die einen Zeigerparameter hat und einen anderen Zeiger zurückggibt, ein Problem? char* foo = malloc( 100 ); strcpy( foo, "Hallo Welt" ); foo = strstr( foo, "ll" ); free foo;[/code] Ohne free -> Speicherleck. Mit free -> Undefiniertes Verhalten. Ist das jetzt ein Problem von strstr? Zitieren
Guybrush Threepwood Geschrieben 29. Mai 2008 Geschrieben 29. Mai 2008 Dann hat also deiner Meinung nach jede Funktion, die einen Zeigerparameter hat und einen anderen Zeiger zurückggibt, ein Problem? Prinzipiell ja Ist das jetzt ein Problem von strstr? Hmm, nein eher eins der Sprache würde ich sagen. Aber das lässt sich ja nicht ändern und auch meine zuerst vorgeschlagene Lösung hat je den großen Nachteil den ich oben geschrieben habe das man den String inklusive Leerzeichen am Anfang komplett verlieren würde. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.