PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [C/C++] Länge des Inhaltes einer Pointervariablen ermitteln


Gast
2010-05-06, 10:10:38
Moin!


unsigned char* bla;
std::string input = "12345678";

bla = new unsigned char[strlen(input.c_str())];

memcpy(bla, input.c_str(), strlen(input.c_str()));


Wie kann ich nun über "bla" ermitteln, wie lang der "in bla gespeicherte" String ist ?

Exxtreme
2010-05-06, 10:20:12
Wenn der String NULL-teminiert ist dann kannst du mit "strlen ( const char * str )" die Länge ermitteln.

Ansonsten geht es auch mit dem sizeof-Operator.

Gast
2010-05-06, 10:43:17
Irgendwie bekomm ich es nicht hin:

int size = sizeof((unsigned char *) bla);

gibt 4 zurück. Mit strlen wird auch was falsches zurückgegeben.

Novox/work
2010-05-06, 10:46:50
sizeof dürfte auch nur mit statisch allozierten Arrays funktionieren, sonst bekommst Du nur die Größe des Pointers geliefert (4 Byte).

Novox/work
2010-05-06, 10:50:19
strlen(bla) funktioniert bei mir übrigens. Wieso eingentlich unsigned char* und nicht char*?

Gast
2010-05-06, 10:52:28
Also wenn ich

int size = strlen((const char*) bla);

ausführe, gibt er immer 24(dezimal) bzw. 0x00000018 zurück. Irgendwie scheint das nicht so wirklich zu funktionieren :).

Neomi
2010-05-06, 10:53:41
Böser Fehler. Weder allokierst du Platz genug, um die terminierende Null noch mitzukopieren, noch kopierst du sie mit. Strings kopiert man auch nicht per memcpy, dafür gibt es nämlich die diversen strcpy-Varianten. In der jetzigen Form liefert strlen im besten Fall falsche Werte (mit Glück evtl auch mal den richtigen, aber das nur zufällig) und im schlechtesten stürzt dir das Programm mit einer Read Access Violation ab, weil auf der Suche nach der terminierenden Null über das Ende des allokierten Blocks hinaus gelesen wird.

Wenn du Pointer verwenden willst, liegt die Verantwortung der Handhabung bei dir, nicht bei der C-Runtime. Wenn du wissen mußt, wie groß der allokierte Speicherbereich zu einem Pointer ist, mußt du dir das merken, bei der Allokierung weißt du die Größe ja. Mit strlen bekommst du ausschließlich für Strings deren Länge, allerdings ohne terminierende Null, auf die Größe des Speicherblocks kommst du dadurch nicht.

Novox/work
2010-05-06, 10:54:09
Das hier funktioniert:


char* bla;
std::string input = "12345678";

bla = new char[strlen(input.c_str())];

memcpy(bla, input.c_str(), strlen(bla));

std::cout << bla << std::endl;


...gibt "12345678" aus.

Exxtreme
2010-05-06, 11:09:27
Irgendwie bekomm ich es nicht hin:

int size = sizeof((unsigned char *) bla);

gibt 4 zurück. Mit strlen wird auch was falsches zurückgegeben.
Versuch mal Folgendes:

int size = sizeof(bla);

Ansonsten würde ich wie Neomi schon schreibt, kein memcpy zum Kopieren von NULL-terminierten Strings nutzen. strcpy ist da wesentlich Fehler unanfälliger.

noid
2010-05-06, 11:27:54
Und vorallem: unsigned char für chars ist zu vermeiden. Wenn man Zeichen abbilden will, dann bitte immer char ohne signed oder unsigned.

(auf char sollte man dann eben auch nur Zuweisungen und Vergleiche nutzen)

Neomi
2010-05-06, 12:26:13
Das hier funktioniert:

Nein, das funktioniert nicht, das ist fatal falsch. Es sieht nur in Abhängigkeit von Compilersettings so aus, weil du in diesem Fall das Ergebnis angezeigt bekommst, das du haben willst. Das ist in etwa so, als würdest du 2+2 und 2*2 vergleichen, sehen daß das Ergebnis gleich ist, und daraufhin eine Addition als identisch zur Multiplikation betrachten.

Es gibt im Internet tonnenweise Dokus und Tutorials zur Verwendung von C-Strings. Es besteht kein Grund, sich einfach irgendwas aus den Fingern zu saugen, bis der Compiler keine Fehler mehr meldet. Leute, die mit C-Strings nicht umgehen können (so wie du zur Zeit), sollten entweder den Umgang damit erlernen oder einfach auf std::string zurückgreifen (was sich auch für geübtere Leute immer dann empfiehlt, wenn kein konkreter Grund dagegen spricht), aber auf keinen Fall mal einfach auf Verdacht mit C-Strings arbeiten.

Simon
2010-05-06, 12:41:21
Wie wärs einfach mit strdup()?

Gast
2010-05-06, 13:04:41
Nein, das funktioniert nicht, das ist fatal falsch. Es sieht nur in Abhängigkeit von Compilersettings so aus, weil du in diesem Fall das Ergebnis angezeigt bekommst, das du haben willst. Das ist in etwa so, als würdest du 2+2 und 2*2 vergleichen, sehen daß das Ergebnis gleich ist, und daraufhin eine Addition als identisch zur Multiplikation betrachten.

Es gibt im Internet tonnenweise Dokus und Tutorials zur Verwendung von C-Strings. Es besteht kein Grund, sich einfach irgendwas aus den Fingern zu saugen, bis der Compiler keine Fehler mehr meldet. Leute, die mit C-Strings nicht umgehen können (so wie du zur Zeit), sollten entweder den Umgang damit erlernen oder einfach auf std::string zurückgreifen (was sich auch für geübtere Leute immer dann empfiehlt, wenn kein konkreter Grund dagegen spricht), aber auf keinen Fall mal einfach auf Verdacht mit C-Strings arbeiten.

Wäre das hier (abgesehen von dem Rumgecaste) auch grober Unfug oder kann ansich nichts Schlimmes passieren:


unsigned char *bla;

std::string input = "123456789";

bla = new unsigned char[strlen(input.c_str())];

strcpy((char *)bla, input.c_str());

Neomi
2010-05-06, 13:16:04
Nimm das unpassende unsigned raus und kürze das dann nicht mehr nötige Casting, dann bleibt nur noch ein Fehler. Auf den Rückgabewert von strlen mußt du noch 1 draufaddieren, um die terminierende Null mit unterbringen zu können, sonst schreibst du beim strcpy über das Ende des allokierten Speichers hinaus und korrumpierst den Heap. Und nicht vergessen, daß du bei manueller Speicherallokierung den auch später manuell wieder freigeben mußt, sonst hast du Speicherlecks.

Warum benutzt du nicht einfach durchgängig std::string?

Exxtreme
2010-05-06, 13:18:24
Wäre das hier (abgesehen von dem Rumgecaste) auch grober Unfug oder kann ansich nichts Schlimmes passieren:


unsigned char *bla;

std::string input = "123456789";

bla = new unsigned char[strlen(input.c_str())];

strcpy((char *)bla, input.c_str());

IMHO ist das da korrekt:

unsigned char *bla;

std::string input = "123456789";

bla = new unsigned char[strlen(input.c_str())+1];

strcpy((char *)bla, input.c_str());

strlen ermittelt nur die Anzahl der Zeichen. Es fehlt aber dann das eine Byte für die NULL-Teminierung. Deshalb das "+1" hintendran.

Gast
2010-05-06, 13:23:36
Warum benutzt du nicht einfach durchgängig std::string?

Ich fummel grad an einem alten Projekt rum und das wurde damals in reinem ANSI-C geschrieben. Ich hab mir das halt irgendwie so angewöhnt und wollte es halbwegs einheitlich belassen.

Du meinst also so wäre es "richtiger" ? ;)


char *bla;
std::string input = "123456789";
bla = new unsigned char[strlen(input.c_str()) + 1];
strcpy(bla, input.c_str());

Gast
2010-05-06, 13:25:25
Ich war zu spät :D
Danke euch!

Neomi
2010-05-06, 13:34:38
Du meinst also so wäre es "richtiger" ? ;)

Wenn du das letzte verbleibende unsigned auch noch rauswirfst, ja.

Gast
2010-05-06, 13:41:21
Wenn du das letzte verbleibende unsigned auch noch rauswirfst, ja.

Ups, übersehen :D

Coda
2010-05-06, 13:57:52
Du meinst also so wäre es "richtiger" ? ;)
Es ist nicht "richtiger", weil nie davor irgendwas richtig war. Es ist jetzt richtig.

Gnafoo
2010-05-06, 15:27:48
Btw. gibt es auch string::length.


std::string input = "123456789";
char* bla = new unsigned char[strlen(input.c_str()) input.length() + 1];

strcpy(bla, input.c_str());

// ...

delete[] bla;

Gast
2010-05-06, 15:40:08
Wenn ich das Ganze wirklich in reinem C machen würde, könnte ich ja statt

std::string input = "123456789";

auch einfach

char input[] = "123456789"

verwenden, oder ? Da wird dann auch gleich das terminierende Nullzeichen mitgeschrieben.

MuLuNGuS
2010-05-07, 08:04:22
Wenn ich das Ganze wirklich in reinem C machen würde, könnte ich ja statt

std::string input = "123456789";

auch einfach

char input[] = "123456789"

verwenden, oder ? Da wird dann auch gleich das terminierende Nullzeichen mitgeschrieben.

so::ist::es() :D

ollix
2010-05-07, 09:47:24
In der jetzigen Form liefert strlen im besten Fall falsche Werte (mit Glück evtl auch mal den richtigen, aber das nur zufällig) und im schlechtesten stürzt dir das Programm mit einer Read Access Violation ab, weil auf der Suche nach der terminierenden Null über das Ende des allokierten Blocks hinaus gelesen wird.Ist das nicht der beste Fall ;)

Neomi
2010-05-07, 10:26:06
Ja, stimmt. Besser ein Absturz als korrumpierte Daten, von denen man ausgeht, daß sie stimmen. Sowas kann richtig böse werden und tritt dann meist kurz vor Ablauf einer wichtigen Deadline ans Licht (falls der Fehler in einem Produktivsystem steckt). Und das Debugging wird auch noch erleichtert im Vergleich zur gemeinen Heap Corruption...

Exxtreme
2010-05-07, 10:44:56
Ist das nicht der beste Fall ;)
Japp. Einmal hatte ich einen sehr bösen Fehler produziert. Beim Abspeichern/Laden der Daten hatte ich den Dereferenzierungsoperator vergessen was dafür sorgte, dass nicht die Daten in die Datei geschrieben wurden sondern die Zeiger. Und da das Programm ein DOS-Programm war und DOS keinen Speicherschutz hat funktionierte alles einwandfrei bis zum nächsten Neustart. X-D