[c++] best practices to debug?

141 views
Skip to first unread message

Shahbaz Chaudhary

unread,
Oct 27, 2015, 9:18:13 PM10/27/15
to FlatBuffers
I'm running an end-to-end test and I am not getting out what I put in.
Luckily the schema is pretty simple:

table MyMessage{ msg: [string]; }

In this array, I populate data like "ABC", "DEF", ...

Here is how I'm populating it:
===============
flaatbuffers::FlatBufferBuilder fbb;
std::vector<Flatbuffers::Offset<flatbuffers::String>> msgs_;

for(auto & element: std_strings){
  auto fb_str = fbb.CreateString(element); <<<<==== A
  msgs_.push_back(fb_str);
}

auto msgs = fbb.CreateVector(msgs_);

MyMessageBuilder e(fbb);

e.add_msgs(msgs);
auto inner_event = e.Finish(); 
...
===============

I step through this code in the debugger inside the for loop as well as near the end, I can see that what is being passed into the CreateString method (line A) is the string "ABC"

At the end, I expect to see "ABC" inside the fbb object (with inner_event showing an offset). However, what I actually see is gibberish. I expect the first three bytes to be 'A', 'B', 'C', perhaps a null terminator, then garbage afterwards. I don't see "ABC" at all (or anything it encodes into).

Naturally if something is wrong at this step, converting from raw bytes back to FB is still going to show garbage. Any ideas?

Wouter van Oortmerssen

unread,
Oct 28, 2015, 1:50:17 PM10/28/15
to Shahbaz Chaudhary, FlatBuffers
On Tue, Oct 27, 2015 at 6:18 PM, Shahbaz Chaudhary <shah...@gmail.com> wrote:
I'm running an end-to-end test and I am not getting out what I put in.
Luckily the schema is pretty simple:

table MyMessage{ msg: [string]; }

In this array, I populate data like "ABC", "DEF", ...

Here is how I'm populating it:
===============
flaatbuffers::FlatBufferBuilder fbb;
std::vector<Flatbuffers::Offset<flatbuffers::String>> msgs_;

for(auto & element: std_strings){
  auto fb_str = fbb.CreateString(element); <<<<==== A
  msgs_.push_back(fb_str);
}

auto msgs = fbb.CreateVector(msgs_);

MyMessageBuilder e(fbb);

e.add_msgs(msgs);
auto inner_event = e.Finish(); 
...

I presume there's a fbb.Finish(inner_event) here?
 
===============

I step through this code in the debugger inside the for loop as well as near the end, I can see that what is being passed into the CreateString method (line A) is the string "ABC"

At the end, I expect to see "ABC" inside the fbb object (with inner_event showing an offset). However, what I actually see is gibberish. I expect the first three bytes to be 'A', 'B', 'C', perhaps a null terminator, then garbage afterwards. I don't see "ABC" at all (or anything it encodes into).

Where are you looking? the value of inner_event is an offset from the end of the buffer inside fbb.

After you've done the Finish I've mentioned above, call fbb.GetBufferPointer(). You should be able to find "ABC" somewhere from that pointer onwards, within fbb.GetSize() bytes.
 
Naturally if something is wrong at this step, converting from raw bytes back to FB is still going to show garbage. Any ideas?

Have you tried?

Wouter

Shahbaz Chaudhary

unread,
Oct 28, 2015, 2:35:54 PM10/28/15
to FlatBuffers, shah...@gmail.com
Hm...I don't have a .Finish(inner_event).

My code is based mostly on examples on http://google.github.io/flatbuffers/md__cpp_usage.html
auto mloc = mb.Finish();
On that page, Finish() doesn't take any parameters. My impression was that if we use the constructor which takes all the parameters up-front, then we call Finish(...). However, if we call the simple constructor and subsequently call .add_XXX, then we call the Finish() method without params.

Is that not the case?

Wouter van Oortmerssen

unread,
Oct 28, 2015, 4:27:35 PM10/28/15
to Shahbaz Chaudhary, FlatBuffers
note I wrote fbb.Finish(inner_event), it's a method on FlatBufferBuilder, not the one one your table builder. The document you reference mentions FinishMonsterBuffer, which does the same (calls that function).

--
You received this message because you are subscribed to the Google Groups "FlatBuffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flatbuffers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shahbaz Chaudhary

unread,
Oct 28, 2015, 6:16:29 PM10/28/15
to FlatBuffers, shah...@gmail.com
Sorry for pasting snippets here and there. If you don't mind, I've pasted much more of the code which shows the schema, how I encode it and how I decode it (although I've changed it a bit to place it on the internet):

Am I doing something obviously wrong?
What I've pasted could serve as another example of how to encode/decode messages, so I'll leave it up on my public gist.

Shahbaz Chaudhary

unread,
Oct 29, 2015, 2:08:10 PM10/29/15
to FlatBuffers, shah...@gmail.com
Deep in the guts of FB, I'm seeing something odd.
In flatbuffers.h, in the CreateString method (line 730), 

After the call to PushBytes(..)
I see that buf_.cur_ has the value I expect, "ABC" and buf_.buf_ also has the value I can understand "...garbage...ABC" (apparently it is appended to the end)

However, after the very next line, PushElement(...)
cur_ now has "\x3" and buf_ now has "...garbage...L" (where L is some weird ascii character, looks like 'L' superscript, but probably not relevant). ABC is gone and replaced with this single char.

As far as I can tell, the string "ABC" is lost within the CreateString(...) method.

In a way, I doubt this is actually the problem since it would show up in everyone's projects, but as far as I can tell, I'm using CreateString correctly.

Shahbaz Chaudhary

unread,
Oct 29, 2015, 2:33:39 PM10/29/15
to FlatBuffers, shah...@gmail.com
Looks like "ABC" is added to the buffer. Then '\x3',\0,\0,\0 is pre-pended. Looks like the \0 makes Visual studio think the string is terminated. Not exactly sure where \x3, \0, \0, \0 are coming from.

Shahbaz Chaudhary

unread,
Oct 29, 2015, 2:58:48 PM10/29/15
to FlatBuffers, shah...@gmail.com
The problem may be around line 39 (in the gist https://gist.github.com/falconair/625c354fb4b92dd6ef81).
I'm creating an FB object, then passing the FlatBufferBuilder and the offset of the built object to a function, which wraps up the object in the root unioned object. Am I doing that wrong?

Shahbaz Chaudhary

unread,
Oct 30, 2015, 2:31:26 PM10/30/15
to FlatBuffers, shah...@gmail.com
This issue is resolved. There were a number of issues, among them being that I wasn't calling .Finish() on intermediate tables, not calling flat_buffer_builder.Finish(...) on the FlatBufferBuilder itself, relying on Visual Studio to look at values (which cuts of string values after the first null character), etc.

Wouter van Oortmerssen

unread,
Nov 2, 2015, 8:55:51 PM11/2/15
to Shahbaz Chaudhary, FlatBuffers
Sorry to hear. I just added a commit recently that has more aggressive asserts for the FlatBufferBuilder not being finished, and for any nesting happening, so that should help detect these case quicker in the future.

Btw that \x3, \0, \0, \0 is the length of the string.
Reply all
Reply to author
Forward
0 new messages