Unexpected sscanf Result - c++

I have a sscanf statement that is behaving unexpectedly. This is somewhere around loop #8000 that it suddenly does this. This is the code, where str is a string parsed from a file:
char a1[6], a2[6], op[6], a3[6];
int success = sscanf(str.c_str(),"%*s %s %*s %s %s %s",a1, a2, op, a3);
And this is the gdb output on the problem line (str is "assign po012 = po011;"):
(gdb) print str
$9 = {<std::__1::__basic_string_common<true>> = {<No data fields>}, static __short_mask = 1, static __long_mask = 1,
__r_ = {<std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {__value_ = {{__l = {__cap_ = 97, __size_ = 23, __data_ = 0x1003001d0 " assign po012 = po011;"}, __s = {{
__size_ = 97 'a', __lx = 97 'a'},
__data_ = "\000\000\000\000\000\000\000\027\000\000\000\000\000\000\000\320\001\060\000\001\000\000"}, __r = {__words = {
97, 23,
4298113488}}}}}, <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {<std::__1::allocator<char>> = {<No data fields>}, <No data fields>}, <No data fields>}, static npos = 18446744073709551615}
(gdb) n
81 string A1(a1);
(gdb) print a1
$10 = "\000o012"
(gdb) print a2
$13 = "po011;"
a2 has the expected value, but what is happening to a1 in just this one case?

Your arrays have length six:
char a1[6], a2[6], op[6], a3[6];
Yet, sscanf causes "po011;" to be written in a2, and this requires seven characters, since sscanf will add the null terminator. Hence, sscanf causes undefined behavior.
Pragmatically, in your implementation the null terminator was added to the beginning of a1, which changed from the intended "po012" to "\000o012" (the initial p was overwritten). It looks like your implementation chose to store a1 right after a2, so overflowing a2 overwrote a1. This is one of the things that can happen when undefined behavior is triggered.

Related

Terminal use gdb to debug .cpp files, (gdb)p command

When I use gdb to debug, I just want to use '(gdb)p x' to print the value of x, but the result is very complicated. Terminal command like this:
(gdb) p word
Output:
$2 = {<std::__1::__basic_string_common<true>> = {<No data fields>}, static __short_mask = 1,
static __long_mask = 1,
__r_ = {<std::__1::__compressed_pair_elem<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep, 0, false>> = {__value_ = {{__l = {__cap_ = 1970239750,
__size_ = 0, __data_ = 0x0}, __s = {{__size_ = 6 '\006', __lx = 6 '\006'},
__data_ = "you", '\000' <repeats 19 times>}, __r = {__words = {1970239750, 0,
0}}}}}, <std::__1::__compressed_pair_elem<std::__1::allocator<char>, 1, true>> = {<std::__1::allocator<char>> = {<No data fields>}, <No data fields>}, <No data fields>},
static npos = 18446744073709551615}
What I really want is __data_ = "you" this segment only.
How can I get a simple result like this:
$2 = "you"
Can someone help me? Very appreciate that.
How can I get a simple result like this:
That's what GDB pretty-printers are for.
It looks like you are using libc++ (and probably Clang).
From libc++ documentation:
GDB does not support pretty-printing of libc++ symbols by default. However, libc++ does provide pretty-printers itself. Those can be used as:
$ gdb -ex "source <libcxx>/utils/gdb/libcxx/printers.py" \
-ex "python register_libcxx_printer_loader()" \
<args>
You can put the source <libcxx>/utils/gdb/libcxx/printers.py and the python register_libcxx_printer_loader() commands into your ~/.gdbinit, and then things will just work™.

Reference a column by a variable

I want to reference a table column by a variable while creating another column but I can't get the syntax:
t0 = Table.FromRecords({[a = 1, b = 2]}),
c0 = "a", c1 = "b",
t1 = Table.AddColumn(t0, "c", each([c0] + [c1]))
I get the error the record's field 'c0' was not found. It is understanding c0 as a literal but I want the text value contained in c0. How to do it?
Edit
I used this inspired by the accepted answer:
t0 = Table.FromRecords({[a = 1, b = 2]}),
c0 = "a", c1 = "b",
t1 = Table.AddColumn(t0, "c", each(Record.Field(_, c0) + Record.Field(_, c1)))
Another way:
let
t0 = Table.FromRecords({[a = 1, b = 2]}),
f = {"a","b"},
t1 = Table.AddColumn(t0, "sum", each List.Sum(Record.ToList(Record.SelectFields(_, f))))
in
t1
try using an index as below
let t0 = Table.FromRecords({[a = 1, b = 2]}),
#"Added Index" = Table.AddIndexColumn(t0, "Index", 0, 1),
c0 = "a",
c1 = "b",
t1 = Table.AddColumn(#"Added Index", "c", each Table.Column(#"Added Index",c0){[Index]} + Table.Column(#"Added Index",c1){[Index]} )
in t1
Expression.Evaluate is another possibility:
= Table.AddColumn(t0, "c", each Expression.Evaluate("["&c0&"] + ["&c1&"]", [_=_]) )
Please refer to this article to understand the [_=_] context argument:
Expression.Evaluate() In Power Query/M
This article explains that argument specifically:
Inside a table, the underscore _ represents the current row, when working with line-by-line operations. The error can be fixed, by adding [_=_] to the environment of the Expression.Evaluate() function. This adds the current row of the table, in which this formula is evaluated, to the environment of the statement, which is evaluated inside the Expression.Evaluate() function.

In GDB, how to print an object so its data members would be listed in alphabetical order?

For instance, by default it would be something like
(gdb) print obj
$1 = {
elephant = 0xb7d28960 <_IO_2_1_stderr_>,
durian = 0x0,
eggplant = 0x809ed58 "",
peanut = 1080,
onion = 0x0,
ice = 0xb7d28c20 <_IO_2_1_stdin_>,
wheat = 0x0,
raspberry = 0x0
}
How to make it become
(gdb) print obj
$1 = {
durian = 0x0,
eggplant = 0x809ed58 "",
elephant = 0xb7d28960 <_IO_2_1_stderr_>,
ice = 0xb7d28c20 <_IO_2_1_stdin_>,
onion = 0x0,
peanut = 1080,
raspberry = 0x0,
wheat = 0x0
}
That is, the data members are listed in alphabetical order.
Thanks.
There's no way to do this that is built in to gdb.
If you really need to do this you could write some Python code that prints objects however you like. You can either write a new command that works like print, or you could write a pretty-printer that recognizes structures and sorts the members.
That said, there are two reasons to keep things the way they are. First, the current order mirrors what is actually written in your source. Second, the current order also shows the layout in memory of the object. Both of these things help reduce confusion.

gdb: Cast memory address to an STL object

I have a memory address that i know is an STL object. Say the address is 0x603340, and I know there is a map there
How do I display the contents of this memory as said object from gdb?
I tried this:
p ('std::map<std::string, std::string*, std::less<std::string>, std::allocator<std::pair<std::string const, std::string*> > >'*) 0x603340
which gets me:
No symbol "std::map<std::string, std::string*, std::less<std::string>, std::allocator<std::pair<std::string const, std::string*> > >" in current context.
Any idea what am I doing wrong? Thanks.
I have taken this as a first step: simple stl containers inspectors for gdb. I did not manage to use pmap directly but I made use of it and create my own scrupt my_pmap:
>cat my.txt
define my_pmap
set $my_obj = *((std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::string*, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::string*> > >*) $arg0)
print $my_obj
set $i = 0
set $node = $my_obj._M_t._M_impl._M_header._M_left
set $end = $my_obj._M_t._M_impl._M_header
set $tree_size = $my_obj._M_t._M_impl._M_node_count
while $i < $tree_size
set $value = (void *)($node + 1)
printf "elem[%u].left: ", $i
p *( std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)$value
set $value = $value + sizeof(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
printf "elem[%u].right: ", $i
p **((std::basic_string<char, std::char_traits<char>, std::allocator<char> >**)$value)
if $node._M_right != 0
set $node = $node._M_right
while $node._M_left != 0
set $node = $node._M_left
end
else
set $tmp_node = $node._M_parent
while $node == $tmp_node._M_right
set $node = $tmp_node
set $tmp_node = $tmp_node._M_parent
end
if $node._M_right != $tmp_node
set $node = $tmp_node
end
end
set $i=$i+1
end
printf "Map size = %u\n", $tree_size
end
Then I wrote a short C++ test program:
#include <map>
#include <string>
#include <iostream>
int main()
{
std::string local_s1 = "Local1";
std::string local_s2= "Local2";
typedef std::map<std::string, std::string*> my_type_t;
my_type_t my_map;
my_map.insert(std::make_pair("Key-string-1", &local_s1));
my_map.insert(std::make_pair("Key-string-2", &local_s2));
my_map.insert(std::make_pair("Key-string-3", &local_s2));
return 0;
}
And then I tested my script:
>gdb -q ./a.out
Reading symbols from /import/home/sergey.kurenkov/src/linux.x64.6.0/tests/test.gdb_map/a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x400c7c: file main.cpp, line 7.
Starting program: /import/home/sergey.kurenkov/src/linux.x64.6.0/tests/test.gdb_map/a.out
Temporary breakpoint 1, main () at main.cpp:7
7 std::string local_s1 = "Local1";
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6.x86_64
(gdb) source my.txt
(gdb) n
8 std::string local_s2= "Local2";
(gdb)
11 my_type_t my_map;
(gdb)
12 my_map.insert(std::make_pair("Key-string-1", &local_s1));
(gdb)
13 my_map.insert(std::make_pair("Key-string-2", &local_s2));
(gdb)
14 my_map.insert(std::make_pair("Key-string-3", &local_s2));
(gdb)
16 return 0;
(gdb) p &my_map
$1 = (my_type_t *) 0x7fffffffe040
(gdb) my_pmap 0x7fffffffe040
elem[0].left: $2 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603088 "Key-string-1"}}
elem[0].right: $3 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603028 "Local1"}}
elem[1].left: $4 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x6030f8 "Key-string-2"}}
elem[1].right: $5 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603058 "Local2"}}
elem[2].left: $6 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603168 "Key-string-3"}}
elem[2].right: $7 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603058 "Local2"}}
Map size = 3
(gdb)

What happens to the string data when std::string objects are passed to functions?

I've noticed something I don't understand happening to the string arguments to functions.
I've written this little test program:
#include <string>
#include <iostream>
using namespace std;
void foo(string str) {
cout << str << endl;
}
int main(int argc, char** argv) {
string hello = "hello";
foo(hello);
}
I compile it like this:
$ g++ -o string_test -g -O0 string_test.cpp
Under g++ 4.2.1 on Mac OSX 10.6, str inside foo() looks the same as it does as hello outside foo():
12 foo(hello);
(gdb) p hello
$1 = {
static npos = 18446744073709551615,
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider:
_M_p = 0x100100098 "hello"
}
}
(gdb) s
foo (str=#0x7fff5fbfd350) at string_test.cpp:7
7 cout << str << endl;
(gdb) p str
$2 = (string &) #0x7fff5fbfd350: {
static npos = 18446744073709551615,
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider:
_M_p = 0x100100098 "hello"
}
}
Under g++ 4.3.3 on Ubuntu, however, it doesn't:
12 foo(hello);
(gdb) p hello
$1 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x603028 "hello"}}
(gdb) s
foo (str={static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff5999e530 "(0`"}}) at string_test.cpp:7
7 cout << str << endl;
(gdb) p str
$2 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7fff5999e530 "(0`"}}
(gdb) p str->_M_dataplus->_M_p
$3 = 0x7fff5999e530 "(0`"
So, what's happening to the value of the string when it is passed to this function? And why the difference between the two compilers?
On my compiler foo() is inlined, so there is only one hello. Perhaps that is what is happening for you too.
What a program looks like in a debugger is not part of the language standard. Only the visible result, like actually printing "Hello", is.