Copy ctor von wstring mit wchar frage
-
Ich benutze die XML Serialisierungsklasse xmlser, dort gyibt es eine Methode , welche mir wstrings aussliest, deren Signatur sieht so aus:
typedef wchar_t UCSChar; bool XmlReader::getString(UCSChar* xpath, UCSChar* str);Ich würde gerne std::wstring zur Verwaltung benutzen, allerdings habe ich Problem, folgendes klappt natürlich nicht:
void readXml(XmlReader& rs) { std::wstring wname; rs.getString(L"/Config/name",wname); }Dies hingegen klappt schon:
std::wstring name; void readXml(XmlReader& rs) { UCSChar * wname = new UCSChar(); rs.getString(L"/Config/name",wname); name = std::wstring(wname); //delete wname; }Wie man sieht ist delete wname; auskommentiert. Wenn ich es unkommentiere, bekomme ich eine heap corruption.
Kann mir jemand erklären wieso? Ich dachte name = std::wstring(wname); kopiert den Inhalt und ich kann wname getrost löschen...
-
Seikilos schrieb:
Kann mir jemand erklären wieso? Ich dachte name = std::wstring(wname); kopiert den Inhalt und ich kann wname getrost löschen...
Naja, das Problem ist eher, dass dein Array nicht gross genug ist, bzw. dass du genau nur ein
wchar_tauf dem Heap anlegst. Also Speicher für genau ein einziges Zeichen.In der Bibliothek wird es wohl irgendwo eine Möglichkeit haben, wo du rausfinden kannst, wieviele Zeichen an der Stelle sind. Ein dementsprechend langes Array musst du dann anlegen und der Funktion übergeben. Zudem musst du nachprüfen, ob das Array von der Funktion auch nullterminiert wird. Dann kannst du es an den Konstruktor von
std::wstringübergeben.Du könntest übrigens auch statt eines C-Arrays einen
std::vector<wchar_t>nehmen oder einboost::scoped_array<wchar_t>.Grüssli
-
Hi, danke für die Antwort.
Sieht im moment nach blinder allokation aus, was? Ich alloziiere soviel Speicher wie ich für ratsam finde und hoffe, dass es ausreicht?Die Signatur der Methode kann ich nicht ändern, die muss nen UCSChar * nehmen und nimmt mir sicher übel, wenn ich da n vektor reinklatsche

-
Eine Xml-Bibliothek, die keine Möglichkeit bietet, vorher die Länge der Daten in Erfahrung zu bringen? O.O
-
Seikilos schrieb:
Hi, danke für die Antwort.
Sieht im moment nach blinder allokation aus, was? Ich alloziiere soviel Speicher wie ich für ratsam finde und hoffe, dass es ausreicht?Nein, du sollst die Dokumentation der Bibliothek lesen oder am besten das Testprojekt anschauen, dann findest du raus, wie man sowas macht, nämlich so:
void readXml(XmlReader& rs) { int length = rs.getStringLength(L"/Config/name"); UCSChar* wname = new UCSChar[length] rs.getString(L"/Config/name",wname); name = std::wstring(wname); delete[] wname; }Seikilos schrieb:
Die Signatur der Methode kann ich nicht ändern, die muss nen UCSChar * nehmen und nimmt mir sicher übel, wenn ich da n vektor reinklatsche

Du musst auch nichts an der Signatur ändern, ich zeig dir mal die zwei Lösungen:
#include <boost/scoped_array.hpp> // ... void readXml(XmlReader& rs) { int length = rs.getStringLength(L"/Config/name"); boost::scoped_array<UCSChar> wname = boost::scoped_array<UCSChar>(new UCSChar[length]); rs.getString(L"/Config/name", wname.get()); name = std::wstring(wname.get()); }#include <vector> // ... void readXml(XmlReader& rs) { static std::vector<UCSChar> buffer; int length = rs.getStringLength(L"/Config/name"); buffer.resize(length); rs.getString(L"/Config/name", &buffer[0]); name = std::wstring(buffer.begin(), buffer.end()); // oder name = std::wstring(&buffer[0]); }(Nicht getestet)
Die zweite Lösung hat einige Vorteile. Sie ist zwar nicht Multithreading tauglich, aber dafür gibt sie den Puffer niemals auf. Es wird immer wieder der gleiche Puffer verwendet und er muss daher nie neu alloziert werden, ausser es wird ein grösserer Puffer benötigt. Aber auch da muss nicht unbedingt neu alloziert werden, da der
std::vectormeistens schon mehr Speicher alloziert, als nötig ist.Auch praktisch ist bei beiden Lösungen, dass die Speicherfreigabe automatisiert wird. So können auch gefahrlos Exceptions geworfen werden, ohne das irgendwelche Speicherlecks entstehen.
Grüssli
-
Interessant, danke für die Infos.
Ich musste die Lib sowieso stark modifizieren, die const correctness geht hier mal garnicht wenn ein UCSChar * genommen wird
-
Seikilos schrieb:
Interessant, danke für die Infos.
Ich musste die Lib sowieso stark modifizieren, die const correctness geht hier mal garnicht wenn ein UCSChar * genommen wirdBist du denn gezwungen diese Bibliothek zu benutzen? Gibt schliesslich auch noch andere XML Bibliotheken, auch kleine.
Grüssli
-
Naja der wechsel würde den aufwand nicht lohnen, wenn anforderungen steigen, werd ich wohl auf tinyxml umsteigen.
Was mich stört, ist dass ich das serialisieren selber schreiben muss, das geht in C# aber besser
-
Seikilos schrieb:
Was mich stört, ist dass ich das serialisieren selber schreiben muss, das geht in C# aber besser

Wenn man der Jungspund (C#) ist, und die Fehler der älteren Generationen (C++/Java/VB/Delphi) kennt, kann man sie umgehen...