Problem mit malloc und new
-
krümelkacker schrieb:
Du hast vergessen, Platz für einen Nullterminator zu machen und diesen mitzukopieren.
Der BOString hat eine Längenangabe und braucht keinen Nullterminator.
-
Buch macht kluch. Einfach mal "Effektiv C++ programmieren" durchlesen. Nur so zur Sicherheit, daß Du nicht gegen die Sprache programmierst.
-
Serious_Bob schrieb:
Das war schon alles, ich wusste nicht, dass der Debugger so weit ließt, ich hänge also einfach noch eine '\0' hinten dran, jetzt zeigt der Debugger auch das richtige an. Danke dir!
Und das möchtest du jedes Mal machen? Verwende lieber das hier:
//Ein zusätzliches Zeichen für '\0': this->len=strlen(str); this->str=new char[this->len+sizeof(char)]; //Ist doch so viel lesbarer und einfacher, oder? for(unsigned int i=0;str[i];i++) this->str[i]=str[i]; this->str[this->len]=0;Serious_Bob schrieb:
Das einzige Problem ist, dass C++ halt sehr Prozessor nah ist und ich da erstmal durchsteigen muss.
Assembler ist sehr nahe am Prozessor, C++ ist nur maschinennah. Durch die hohe Abstraktion ist man in C++ in der Lage, Low-Level-Befehle mit einfachen Funktionen aufzurufen, die zudem plattformunabhängig sein können.
Serious_Bob schrieb:
Die Klasse ist noch lange nicht fertig, aber danke für den Tipp!
Das void im Destruktor ist auch nicht beabsichtigt gewesen, das ist noch vom Erstellen der Klasse übrig. Die Windows-spezifische main-Funktion wird später mal wichtig werden für mich.Eine Klasse ist eine Klasse, kein Programm. Und selbst, wenn der gesamte Quellcode in einer Klasse steckt, wird sie doch nicht zum Programm. Kapselung heißt das Zauberwort, und wenn ein Befehl in deiner Klasse Auswirkungen auf das Programm an sich (und nicht nur auf die Instanz) hat, solltest du das Design noch einmal überdenken - später kannst du dann mit deiner geschlossenen Klasse programmieren, ohne darüber nachdenken zu müssen, wie du was implementiert hast.
-
Der aus dem Westen ... schrieb:
Und das möchtest du jedes Mal machen? Verwende lieber das hier:
//Ein zusätzliches Zeichen für '\0': this->len=strlen(str); this->str=new char[this->len+sizeof(char)]; //Ist doch so viel lesbarer und einfacher, oder? for(unsigned int i=0;str[i];i++) this->str[i]=str[i]; this->str[this->len]=0;Ihgittigitt.
Nö, nicht so nachmachen.
-
Verklärst du mir auch, warum, wieso und weshalb?
Nun gut, es mögen Leerzeichen fehlen, aber jeder hat nun mal seinen Stil ...
-
Der aus dem Westen ... schrieb:
//Ein zusätzliches Zeichen für '\0': this->len=strlen(str); this->str=new char[this->len+sizeof(char)]; //Ist doch so viel lesbarer und einfacher, oder? for(unsigned int i=0;str[i];i++) this->str[i]=str[i]; this->str[this->len]=0;Was daran lesbarer sein soll...?!
sizeof(char) ist immer 1.BOBString::BOBString(const char *str) { // FIXME: str auf NULL überprüfen, sonst kracht es. this->str = new char[this->len = std::stlren(str) + 1]; std::strcpy(this->str, str); }
-
sizeof char == 1 schrieb:
Was daran lesbarer sein soll...?!
Für mich ist es nun mal lesbarer, find' dich damit ab. Jedes mal, wenn jemand
int * Pointer = new int [10];schreibt, möchte ich gleichzeitig heulen und den Programmierer strangulieren.
BOBString::BOBString(const char *str) { // FIXME: str auf NULL überprüfen, sonst kracht es. this->str = new char[this->len = std::stlren(str) + 1]; std::strcpy(this->str, str); }Das einzige, was mir (schon vorher, und zwar Sekunden vor deinem Post) aufgefallen ist, ist dass ich wohl
mallocundnewein bisschen durcheinandergebracht habe (sizeof, was habe ich mir dabei gedacht ... :().Zeiger auf NULL prüfen ist nicht nötig, bei
newwird einfach einestd::bad_alloc-Exception geworfen. Mann, das habe ich mal voll ausgenutzt ... imcatch-Block eingotoauf hintertry, und ich hatte blitzschnell 2 Gigabyte reservierten Speicher ...
-
Und selbst, wenn sizeof(char)!=1 wäre, dann wäre
str=new char[this->len+sizeof(char)];erst recht töricht, weil in [] die Anzahl steht und nicht die Größe in Bytes.
Aber mir scheint, Du wolltest damit rohen Speicher besorgen.
Das macht man wiederum mitstr=::operator new(len+1);Und wenn man schon strlen benutzt, darf's auch ein bißchen memcpy sein.
Lesbarer fände ich die Schleife mit str[i]!='\0'.
Die Schleife ist seltsam. Sie soll auf jeden Fall mindestens einen char kopieren? Der FI/AE würde das eine fußgesteuerte Schleife nennen. K&R würden while(*dst++=*src++); schreiben. Irgendwie weigert sie sich, hübsch zu werden.
-
Wieso wird denn hier ständig this verwendet, wo es nicht nötig ist? Es bläht den Code unnötig auf, und das empfinde ich persönlich als schlecht lesbar.
-
Der aus dem Westen ... schrieb:
Jedes mal, wenn jemand
int * Pointer = new int [10];schreibt, möchte ich gleichzeitig heulen und den Programmierer strangulieren.
Geht mir ähnlich. Aber waagerecht noch nicht so schlimm.
Es gibt Leute, die machen es senkrecht!this->len=strlen(str); this->str=new char[this->len+sizeof(char)]; //Ist doch so viel lesbarer und einfacher, oder? for(unsigned int i=0;str[i];i++) this->str[i]=str[i]; this->str[this->len]=0;
-
Serious_Bob schrieb:
Buch?
Ne ich hab Kenntnisse in Java, C#, ABAP, PHP.
Für C++ wollt ich mir nicht auch noch ein Buch kaufen
Ich sehe da keinen Zusammenhang. C++ ist eine völlig andere Sprache. Du tust so, als ob C++ nur ein Dialekt von anderen Dir bekannten Sprachen sei. Da irrst Du Dich aber gewaltig. Du kannst Dir mit einem guten C++ Buch viel Ärger und Zeit sparen. Zeit ist Geld. Glaub's mir, die Investition lohnt sich.
Kompakte Grundausbilding:
- Accelerated C++ (Andrew Koenig & Barbara E. Moo)
- Effective C++ (Scott Meyers)Serious_Bob schrieb:
Das einzige Problem ist, dass C++ halt sehr Prozessor nah ist und ich da erstmal durchsteigen muss.
In C++ kannst Du Dir die Füße abschießen, ja. Umso wichtiger sind gute Bücher, die Dir die Konzepte der Sprache und bewährte Vorgehensweisen näher bringen.
-
volkard schrieb:
Aber mir scheint, Du wolltest damit rohen Speicher besorgen.
Ja, ich habe bereits gesagt, dass ich da Unsinn geschrieben habe. Ich gebe es zu.
volkard schrieb:
Und wenn man schon strlen benutzt, darf's auch ein bißchen memcpy sein.
Hätte ich auch gleich tun können, dafür war ich aber schlichtweg zu faul.
volkard schrieb:
Die Schleife ist seltsam. Sie soll auf jeden Fall mindestens einen char kopieren? Der FI/AE würde das eine fußgesteuerte Schleife nennen. K&R würden while(*dst++=*src++); schreiben. Irgendwie weigert sie sich, hübsch zu werden.
str[i]bedeutet, dass überprüft wird, ob in dem jeweiligen Element ein Nullterminierungszeichen steht. Wenn ja, wird die Schleife abgebrochen, und deshalb wird bei einem leeren String auch nur die 0 eingefügt. Die Anführungszeichen und den Schrägstrich spare ich mir, weil'\0'soweit ich weiß äquivalent zu 0 ist. Insofern würde ich (ohne weitere Kenntnisse darüber, wie hinterher der Maschinencode aussieht) sagen, dass die Schleife ihren Zweck sehr performant erfüllt, oder?@_matze: Ein Parameter von ihm heißt 'str', genauso wie ein Element. Ich hätte es auch rausnehmen können (und glaub' mir, ich war kurz davor), aber dann hat mich wieder die Faulheit übermannt.
volkard schrieb:
Geht mir ähnlich. Aber waagerecht noch nicht so schlimm.
Es gibt Leute, die machen es senkrecht!Hat auch was von psychischer Folter, zumindest, wenn man Zwangsneurotiker ist.
-
Der aus dem Westen ... schrieb:
@_matze: Ein Parameter von ihm heißt 'str', genauso wie ein Element. Ich hätte es auch rausnehmen können (und glaub' mir, ich war kurz davor), aber dann hat mich wieder die Faulheit übermannt.
Das ist mir schon aufgefallen. Ich habe aber nach den Stellen gefragt, an denen this unnötigerweise verwendet wird. Und wenn man konsistent bleiben will, ist es wohl ratsamer, Member oder Parameter umzubenennen, anstatt an ausnahmslos jeder Stelle "this->" zu notieren. Das ist dann letzten Endes auch weniger Arbeit, also der Faulheit zuträglich.

-
Der aus dem Westen ... schrieb:
str[i]bedeutet, dass überprüft wird, ob in dem jeweiligen Element ein Nullterminierungszeichen steht. Wenn ja, wird die Schleife abgebrochen, und deshalb wird bei einem leeren String auch nur die 0 eingefügt. Die Anführungszeichen und den Schrägstrich spare ich mir, weil'\0'soweit ich weiß äquivalent zu 0 ist. Insofern würde ich (ohne weitere Kenntnisse darüber, wie hinterher der Maschinencode aussieht) sagen, dass die Schleife ihren Zweck sehr performant erfüllt, oder?Nicht performanter also mit dem Vergleich gegen den Nullterminator.
Du läufst, solange str[i] wahr ist.
Ich laufe, solange str[i] nicht der Nullterminator ist.
-
volkard schrieb:
Nicht performanter also mit dem Vergleich gegen den Nullterminator.
Du läufst, solange str[i] wahr ist.
Ich laufe, solange str[i] nicht der Nullterminator ist.Und sofern mich meine kümmerlichen C/C++-Kenntnisse nicht trügen, ist
wahr == (!Nullterminator), oder? Der Nullterminator enthält ja den Wert 0, und der ist negativ, während jedes andere Zeichen positiv ist (zumindest, sofern mich mein Wissen um ASCII, den verschiedenen Codepages und den Unicode-Formaten nicht auf das Glatteis führen). Daher verstehe ich nicht ganz, was du mir sagen willst ...
-
Der aus dem Westen ... schrieb:
volkard schrieb:
Nicht performanter also mit dem Vergleich gegen den Nullterminator.
Du läufst, solange str[i] wahr ist.
Ich laufe, solange str[i] nicht der Nullterminator ist.Und sofern mich meine kümmerlichen C/C++-Kenntnisse nicht trügen, ist
wahr == (!Nullterminator), oder? Der Nullterminator enthält ja den Wert 0, und der ist negativ, während jedes andere Zeichen positiv ist (zumindest, sofern mich mein Wissen um ASCII, den verschiedenen Codepages und den Unicode-Formaten nicht auf das Glatteis führen). Daher verstehe ich nicht ganz, was du mir sagen willst ...Ich finde, daß meine Schreibweise eher Klartext ist, während Deine ein kleines Rätsel beinhaltet. Rätsel im Code sind böse meist. Es geht nicht darum, zu zeigen, daß man so vertraut mit C++ ist, daß man sowas normalerweise recht flüssig hinschreiben kann (das können wir alle). Es geht darum, daß man den Code auch noch stockbesoffen recht flüssig lesen kann.
-
Was mich immer noch wundert ist, dass es auf 3 Seiten keiner geschafft hat, die Initialisierungsliste ins Spiel zu bringen?
class BOBString { public: BOBString(const char *str); ~BOBString(void); private: int len; // die Reihenfolge hab ich umgedreht, char *str; // sonst serviert einem der Compiler eine Warnung }; BOBString::BOBString(const char* str) : len(std::strlen(str)), str(new char[len + 1]) { // String kopieren // ... }Wo ich mir jetzt nicht sicher bin, ob strlen() für Null-Zeiger so funktioniert, dass 0 zurückgegeben wird, aber da kann man ja schnell mit ?: Abhilfe schaffen.

-
bmario schrieb:
Wo ich mir jetzt nicht sicher bin, ob strlen() für Null-Zeiger so funktioniert, dass 0 zurückgegeben wird, aber da kann man ja schnell mit ?: Abhilfe schaffen.

Wozu? Wer 0 übergibt, ist selber schuld. Fertig.