2012-03-28 5 views
1

Ich versuche, eine Zeichenfolge an eine andere anzuhängen. Ich deklariere zwei globale String-Variablen -Valgrind beschwert sich auf string.append (string)

Dann habe ich eine Funktion zum Abrufen von Befehlszeilenargumenten. Wann immer ein Benutzer einen Dateinamen in ein Befehlszeilenargument eingibt, sollte er im Ruhezustand gespeichert werden, und dann wird rest an grid_filename angehängt.

else if(strcmp(temp.substr(0,16).c_str(), "--grid-filename=") == 0) { 
    rest = temp.substr(16,strlen(temp.c_str())-16); 
    grid_filename.append(rest); //line 74! 
} 

Nun, wenn ich meinen Code ausführen, gibt valgrind mir diesen Fehler -

==5602== Address 0x45fdc30 is 0 bytes after a block of size 32 alloc'd 
==5602== at 0x402641D: operator new(unsigned int) (vg_replace_malloc.c:255) 
==5602== by 0x43039F7: std::string::_Rep::_S_create(unsigned int, unsigned int,  std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x4304C77: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x4304DA6: std::string::reserve(unsigned int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x43053E9: std::string::append(std::string const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x804D5AE: get_command_line_args(int, char**) (main.cpp:74) 
==5602== by 0x804F138: main (main.cpp:244) 

ich drucken die beiden Adressen der Saiten und keiner von ihnen entsprechen derjenige valgrind sagt 0 Byte ist. Was fehlt mir hier?

Ich glaube, das führt zu meinem zweiten Fehler, weil ich Grid_filename an eine andere Funktion übergeben, die die Zeichenfolge über eine TCP-Verbindung sendet. Valgrind sagt mir

==5660== Syscall param socketcall.send(msg) points to unaddressable byte(s) 
==5660== at 0x404A9B1: send (socket.S:64) 
==5660== by 0x804F7C8: main (main.cpp:364) 

Kann mir jemand erklären, was das Problem ist? Jede Hilfe wäre willkommen. Ich kann bei Bedarf mehr über den Code liefern.

+1

Güte! ...... –

+0

Die erste Fehlermeldung, die Sie eingeben, ist nicht vollständig. Die echte Fehlermeldung muss direkt über dem Text sein, den Sie eingefügt haben, etwas über das Lesen oder Schreiben in 0x45fdc30. Dann druckt valgrind die Nachricht, die Sie eingefügt haben, und sagt Ihnen etwas über diese Adresse. – wolfgang

+0

Die zweite Fehlermeldung, die ich gepostet habe, tritt direkt über der ersten, die ich gepostet habe, auf. Ich dachte, dass sie getrennt waren, also schrieb ich separat über sie. Die gesamte Nachricht sollte mit dem "Syscall param socketcall.send (msg) auf nicht adressierbare Byte (s)" gefolgt von der "Adresse 0x45fdc30 ist 0 Bytes nach einem Block der Größe 32 zugewiesen" Nachricht beginnen. – Sterling

Antwort

0

Über Ihren ersten Fehler: Wir hatten falsche Valves in Valgrind. Überprüfen Sie die documentation, um diese zu unterdrücken, vor allem, wenn sie nicht auf Ihren Code zeigen (und Sie haben überprüft, dass sie tatsächlich keine Probleme verursachen)

0

Hinweis: Dies ist keine Antwort, dies ist keine Code-Review-Website ... aber ich kann wirklich nicht darauf starren und weggehen.

Zunächst einige Funktionen, die wirklich in einer Toolbox helfen: zu

// Some free functions (because there are too many string types) 
inline char const* c_str(std::string const& s) { return s.c_str(); } 
inline size_t size(std::string const& s) { return s.size(); } 

inline char const* c_str(char const* s) { return s; } 
inline size_t size(char const* s) { return std::strlen(s); } 

template <size_t N> 
char const* c_str(char const (&s)[N]) { return s; } 
template <size_t N> 
size_t size(char const (&s)[N]) { return N - 1; } 

// A helper function (lowest common denominator) 
inline bool beginsWith(char const* big, size_t const bigSize, 
         char const* small, size_t const smallSize) 
{ 
    if (bigSize < smallSize) { return false; } 
    return std::memcmp(big, small, smallSize) == 0; 
} 

// The actual function, doing the adaptation from the various forms of string 
template <typename T, typename U> 
bool beginsWith(T& big, U& small) { 
    return beginsWith(c_str(big), size(big), c_str(small), size(small)); 
} 

// same with endsWith 

Und dann können Sie den Code recht effizient (ohne zusätzliche Speicherzuweisung) und mit mehr Lesbarkeit umschreiben:

static std::string const GridFilenameOpt = "--grid-filename="; 

// ... 
else if (beginsWith(temp, GridFilenameOpt)) { 
    grid_filename.append(temp, GridFilenameOpt.size(), std::string::npos); 
} 

Was für die eigentliche Frage nicht viel hilft, da Sie nicht den Code zeigen, der den Fehler verursacht.

+0

Wenn Sie 'anfängtWith' wollen, warum nicht einfach' bool beginntWith (String const & a, String const & b) {return a.vergleichen (0, b.length(), b);} '? –

+0

@JerryCoffin: Ich mag die Idee nicht, eine falsche temporäre 'Zeichenfolge' zu ​​erstellen, nur um diesen Vergleich zu machen. Das Problem ist, dass das Aufzählen aller Kombinationen der 3 Zeichenkettentypen von C++ ('std :: string' und' char const * 'plus das optimierbare' char const (&) [N] ') langweilig ist, also tendiere ich dazu, sie zu vereinheitlichen Interface in den kleinsten gemeinsamen Nenner (eigentlich ... zu Hause benutze ich eine Klasse ähnlich wie 'llvm :: StringRef' für diese Vereinheitlichung). –

+0

Die obige Funktion sollte keine neue Zeichenfolge für den Vergleich erstellen. Es verwendet nur die "compare" -Mitgliedfunktion, mit der Sie einen Anfangspunkt und eine Länge für den Vergleich angeben können. Es ist nur für 'string' geschrieben, aber es wäre trivial generalize für' basic_string' im Allgemeinen. Gleichzeitig ist die Verwendung von 'memcmp 'in sich selbst ziemlich restriktiv ... –

Verwandte Themen