In my C++ program I have a nested class defined as follows:
class A {
class B {
// ...
}
// ...
}
When I try casting a pointer in GDB like this: set $b = (A::B*)p
I get "A syntax error in expression"
I'm not familiar with the symbol (or debugging) information stored in the ELF files. I'm wondering what's wrong with my casting here and how to refer to a nested class in GDB.
The answer is to enclose the class name in single quotes:
set $b = ('A::B'*)p
See http://sourceware.org/bugzilla/show_bug.cgi?id=8693
Works for me (using current CVS GDB, as well as 7.3.1):
$ cat t.cc
struct A {
struct B {
int x;
};
int y;
};
int main()
{
A::B ab, *p = &ab;
return 0;
}
$ gcc -g t.cc && gdb -q ./a.out
(gdb) b main
Breakpoint 1 at 0x4005b8: file t.cc, line 10.
(gdb) r
Breakpoint 1, main () at t.cc:10
10 A::B ab, *p = &ab;
(gdb) p (A::B*)0x1
$1 = (A::B *) 0x1
(gdb) set $a = (A::B*)0x1
(gdb) p $a
$2 = (A::B *) 0x1
(gdb) quit
Related
According to gdb docs, I can automatically continue after stopping on a breakpoint like this:
break 403
commands
cont
end
I'm trying to conditionally continue after a breakpoint like this:
set confirm off
set pagination off
define test
printf "%d\n", $x
set $x = $x + 1
if $x == 1
cont
end
end
break 403
commands
test
end
This almost works.
gdb indeed stops and checks for the condition ($x == 1). However it does not continue immediately when the condition is true.
Instead it just shows the prompt. If I click ENTER it either continues execution (when $x == 1), or remains in the prompt (if $x != 1).
Currently I just hit ENTER enough times until it does not continue execution any more.
But why does it wait for ENTER?
(This is not a matter of pagination/confirmation as I set them both to off)
Update1
Seems to be related to macro usage?
It does not happen if using commands directly.
Update 2
For clarity, here is a complete session that demonstrates the problem:
$ gdb a.out
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
(gdb) set confirm off
(gdb) set pagination off
(gdb) define test
Type commands for definition of "test".
End with a line saying just "end".
>p i
>if i < 3
>cont
>end
>end
(gdb) b 8
Breakpoint 1 at 0x115e: file test.c, line 8.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>test
>end
(gdb) run
Starting program: /home/amir.gonnen/projects/test/gdb-cont/a.out
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
$1 = 0
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
(gdb) echo Hey gdb why is the prompt?
Hey gdb why is the prompt?$2 = 1
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
(gdb) echo Hey gdb you show the prompt but you still continue!
Hey gdb you show the prompt but you still continue!$3 = 2
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
(gdb) echo again...
again...$4 = 3
(gdb) echo not continuing any more.
not continuing any more.(gdb)
not continuing any more.(gdb)
not continuing any more.(gdb)
This appears to work fine for me using GDB-10.0 on x86_64.
Are you sure it doesn't work? One thing I noticed is that you print $x before incrementing and checking it, which makes it a bit confusing.
Here is my session:
# gdbinit
set confirm off
set pagination off
define test
set $x = $x + 1
printf " x = %d\n", $x
if $x == 1
printf " continuing\n"
cont
end
end
set var $x = -2
gdb -q ./a.out
(gdb) source gdbinit
(gdb) list
1 int main()
2 {
3 int k = 0;
4 for (int j = 1; j < 100; j++) {
5 k += 1;
6 }
7 return k;
8 }
(gdb) b 5
Breakpoint 1 at 0x1139: file t.c, line 5.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>test
>end
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, main () at t.c:5
5 k += 1;
x = -1
(gdb) c
Continuing.
Breakpoint 1, main () at t.c:5
5 k += 1;
x = 0
(gdb) c
Continuing.
Breakpoint 1, main () at t.c:5
5 k += 1;
x = 1
continuing <<<=== Note: no 'c' required this time.
Breakpoint 1, main () at t.c:5
5 k += 1;
(gdb)
I have a file named testing.cpp:
#include <iostream>
#include <string>
struct Foo {
std::string name;
};
int main() {
Foo* foo = new Foo;
foo->name = "hello";
std::cout << foo->name << "\n";
return 0;
}
I compiled it to a.out, and start gdb using gdb a.out.
GNU gdb (Debian 7.10-1.1) 7.10
...
Reading symbols from a.out...done.
(gdb)
I break at line 12 (std::cout << foo->name << "\n";), and run:
(gdb) break 12
Breakpoint 1 at 0x400990: file testing.cpp, line 12.
(gdb) run
Starting program: ...
Breakpoint 1, main () at testing.cpp:12
12 std::cout << foo->name << "\n";
(gdb)
It can print foo->name and foo->name.c_str():
(gdb) print foo->name
$1 = "hello"
(gdb) print foo->name.c_str()
$2 = 0x613c30 "hello"
It can print boolean expression with foo->name.c_str() in the first clause:
(gdb) print foo->name.c_str() && 1
$3 = true
But it can't when I put foo->name.c_str() in second clause:
(gdb) print 1 && foo->name.c_str()
Attempt to take address of value not located in memory.
(gdb)
Is this a bug?
Edit 1:
Use Case
I was trying to use break ... if ... to break at some point if some strings have certain values. E.g.
(gdb) break 14 if foo->name.size() == 5 && $_streq(foo->name.c_str(), "house")
Breakpoint 2 at 0x400aba: file testing.cpp, line 14
(gdb)
When I continue, gdb show the error message and break at line 14 (return 0;) even though foo->name is "hello" but not "house".
(gdb) continue
Continuing.
hello
Error in testing breakpoint condition:
Attempt to take address of value not located in memory.
Breakpoint 2, main () at testing.cpp:14
14 return 0;
(gdb)
Currently a workaround is access data member of std::string directly:
(gdb) break 14 if foo->name.size() == 5 && \
$_streq(foo->name._M_dataplus._M_p, "house")
Some Observations
Is it because my foo is pointer?
Nope. I tried to use Foo foo; instead of Foo* foo = new Foo;. Problem remains.
Does this problem apply for std::string variable created in main(), oppose to as a data member of some object?
Nope. Seems like it only applies for std::string as a data member. Code below works:
(gdb) list 4,8
4 int main() {
5 std::string name("hello");
6 std::cout << name << "\n";
7 return 0;
8 }
(gdb) break 6
Breakpoint 1 at 0x400a93: file testing.cpp, line 6
(gdb) run
Starting program: ...
Breakpoint 1, main() at testing.cpp:6
6 std::cout << name << "\n";
(gdb) print 1 && name.c_str()
$1 = true
Does this problem unique to c_str() only? How about other function?
No, this problem is not unique to c_str(). It is not even unique to std::string. Seems like it happens when we call member function of object inside another object, i.e. foo.bar.func().
This has probably been asked elsewhere, but was a bit of a tricky one to google.
I am debugging some code like the following in gdb (or cgdb more specifically):
if(something) {
string a = stringMaker();
string b = stringMaker();
}
As I step through using 'n', the cursor will reach the 'string b' line. At this point I can inspect the value of a, but b won't have been populated yet as that line hasn't been executed. Another press of 'n' will execute that line, but will then also move outside the if loop and b will now be out of scope. Is there a way to execute the current line without moving on so that its result can be inspected before it goes out of scope?
Another press of 'n' will execute that line, but will then also move
outside the if loop and b will now be out of scope
The problem is that next executes too much instructions and b variable becomes unavailable. You can substitute this single next with a number of step and finish commands to achieve more granularity in debugging and stop immediately after b was constructed. Here is sample gdb session for test program:
[ks#localhost ~]$ cat ttt.cpp
#include <string>
int main()
{
if (true)
{
std::string a = "aaa";
std::string b = "bbb";
}
return 0;
}
[ks#localhost ~]$ gdb -q a.out
Reading symbols from a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x40081f: file ttt.cpp, line 7.
Starting program: /home/ks/a.out
Temporary breakpoint 1, main () at ttt.cpp:7
7 std::string a = "aaa";
(gdb) n
8 std::string b = "bbb";
(gdb) p b
$1 = ""
(gdb) s
std::allocator<char>::allocator (this=0x7fffffffde8f) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/allocator.h:113
113 allocator() throw() { }
(gdb) fin
Run till exit from #0 std::allocator<char>::allocator (this=0x7fffffffde8f) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/allocator.h:113
0x0000000000400858 in main () at ttt.cpp:8
8 std::string b = "bbb";
(gdb) s
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffffffde70, __s=0x400984 "bbb", __a=...) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:656
656 basic_string<_CharT, _Traits, _Alloc>::
(gdb) fin
Run till exit from #0 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffffffde70, __s=0x400984 "bbb", __a=...) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:656
0x000000000040086d in main () at ttt.cpp:8
8 std::string b = "bbb";
(gdb) p b
$2 = "bbb"
Just add to the code b; the line afterwards. i.e.
if(something) {
string a = stringMaker();
string b = stringMaker();
b; // Break point here
}
Well you can always to a
(gdb) p stringMaker();
regardless of the line you're in given that stringMaker() is accessible. You can execute any kind statements , even involving variables if those variables are in current scope. For more advanced usage, you can use gdb's internal variables($1,$2 etc) to store certain result to use it later when the variables involved in that previous computation went out of scope.
Finally God(whatever that may be) send us gdb Python API. just type py and demolish your code to such extent that you will forget what you were doing at the first place.
Does it exist an any cpp code parser to solve this problem? For example
// B.cpp : Defines the entry point for the console application.
//
#include<iostream>
#include<vector>
#include<algorithm>
size_t N,M;
const size_t MAXN = 40000;
std::vector<std::pair<size_t,size_t> > graph[MAXN],query[MAXN],qr;
size_t p[MAXN], ancestor[MAXN];
bool u[MAXN];
size_t ansv[MAXN];
size_t cost[MAXN];
size_t find_set(size_t x){
return x == p[x] ? x : p[x] = find_set(p[x]);
}
void unite(size_t a, size_t b, size_t new_ancestor){
}
void dfs(size_t v,size_t ct){
}
int main(int argc, char* argv[]){
return 0;
}
This file has 10 global variables : ancestor, ansv, cost, graph, M, N, p, qr, query, u
You could invoke the compiler and count the exported global variables with the following shell command:
$ g++ -O0 -c B.cpp && nm B.o | grep ' B ' | wc -l
10
If you remove the line count, you get their names
$ g++ -O0 -c B.cpp && nm B.o | egrep ' [A-Z] ' | egrep -v ' [UTW] '
00000004 B M
00000000 B N
00111740 B ancestor
00142480 B ansv
00169580 B cost
00000020 B graph
000ea640 B p
000ea620 B qr
00075320 B query
00138840 B u
Let's see how this works.
g++ -O0 -c B.cpp: This calls the compiler without optimizations such that the output (B.o by default) is pretty much the compiled file without removed identifiers.
nm B.o: Calls nm a tool that (quote from link) "list symbols from object files". If, for example "the symbol is in the uninitialized data section", there is a "B".
We want to have global values (means uppercase) but not U, T or W. This is what the grep does.
I am trying to create an XML parser in C++. I am currently using cygwin and gcc to compile and gdb to debug. I have this piece of code:
const size_t mDataSize = mData.size();
...
size_t ltPos = mData.find_first_of('<', pos);
if (ltPos==mData.npos) {
...
mData is declared as private const std::string & within the class and holds the XML file content. After debugging with gdb I found the following:
(gdb) print pos
$12 = 636
(gdb) print mDataSize
$13 = 2692
(gdb) n
141 size_t ltPos = mData.find_first_of('<', pos);
(gdb) print ltPos
$14 = 114
(gdb) print pos
$15 = 636
(gdb) n
143 if (ltPos==mData.npos)
(gdb) print ltPos
$16 = 4294967295
(gdb) print mData[636]
$17 = (const char &) #0xb2b2a8: 10 '\n'
(gdb) print mData[637]
$18 = (const char &) #0xb2b2a9: 32 ' '
(gdb) print mData[638]
$19 = (const char &) #0xb2b2aa: 32 ' '
(gdb) print mData[639]
$20 = (const char &) #0xb2b2ab: 60 '<'
I was expecting 639 as result of calling find_first_of, but I am getting 4294967295 (which is -1 in a signed 32-bit int and matches std::string::npos). Can someone justify this behaviour? Or tell me how to workaround this?
So mData is declared as a reference? If so it doesn't really hold the content it holds a reference to the content. Is the thing to which mData refers still in existence at the time you're calling find_first_of?