Hello,
I've recently run into a problem with a (newly-written) custom
protobuf decoder, and I've narrowed down the issue to this simple
program:
"""
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
inline void STLStringResizeUninitialized(string* s, size_t new_size) {
s->resize(new_size);
}
inline char* string_as_array(string* str) {
// DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
return str->empty() ? NULL : &*str->begin();
}
int main(int argc, char** argv) {
string output;
STLStringResizeUninitialized(&output, 5);
string_as_array(&output);
cout << "output: " << output << endl;
return 0;
}
"""
Running this in a gdb session:
Breakpoint 1, main (argc=1, argv=0x7fffffffdf48) at simple_repro.cc:18
18 string output;
(gdb) n
19 STLStringResizeUninitialized(&output, 5);
(gdb)
20 string_as_array(&output);
(gdb) p *output._M_rep()
$1 = {<std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep_base> = {_M_length = 5,
_M_capacity = 5, _M_refcount = 0}, static _S_max_size = <optimized
out>, static _S_terminal = <optimized out>,
static _S_empty_rep_storage = {0, 0, 0, 0}}
(gdb) n
21 cout << "output: " << output << endl;
(gdb) p *output._M_rep()
$2 = {<std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep_base> = {_M_length = 5,
_M_capacity = 5, _M_refcount = -1}, static _S_max_size =
<optimized out>, static _S_terminal = <optimized out>,
static _S_empty_rep_storage = {0, 0, 0, 0}}
Note that the refcount went down to -1 after string_as_array is run.
I've reproduced this with gcc-4.5, 4.4, and 4.3 (for some reason I'm
having trouble building 4.1). Obviously I didn't start with this
program, the initial code was something like
func() {
string ret;
...
cis->ReadString(&ret, length);
...
return ret;
}
And I would get an abort() in ~basic_string (sometimes, not always) like:
*** glibc detected *** free(): invalid next size (fast): 0x00007fffdc083e90 ***
on the "return ret" line. The function didn't really do very much else
with ret in those cases. Changing the code to
output.resize(val32);
if (!cis_->ReadRaw((void *)output.c_str(), val32)) {
made everything work. I obviously realize that this is not a great way
to go, but I do think it ends up working in my specific situation.
However the effectively double-free (or at least ref-count-decrease)
seems quite worrying...
Any ideas? Should that string_as_array thing really work and I should
direct this at the gcc people?
Thanks,
-ilia
--
You received this message because you are subscribed to the Google Groups
"Protocol Buffers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/protobuf?hl=en.