3

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?

rbennett485
  • 1,907
  • 15
  • 24
  • I don't think this can be done with gcc or other compilers that only emit source-to-compiled-code mappings at the granularity of a line. As a workaround, you can set a breakpoint at the `string b =` line with an attached command that does `watch b`, then continues. gdb ought to stop just after `b` is written to, although this might be in the middle of a constructor or other string class code rather than in your code. – Mark Plotnick Nov 25 '15 at 16:25
  • `watch` looks like a reasonable answer, that seems about as close as I can get to what I wanted. If you put that as an answer I'll accept it – rbennett485 Nov 25 '15 at 16:48

3 Answers3

1

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"
ks1322
  • 33,961
  • 14
  • 109
  • 164
  • This works for me. I can run `s` followed by `fin` on any command that has underlying implementation. Of course doing it in a single command would be preferred. – dekuShrub Dec 31 '20 at 09:04
0

Just add to the code b; the line afterwards. i.e.

if(something) {
  string a = stringMaker();
  string b = stringMaker();
  b; // Break point here
}
Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • This kind of works - it's obviously not ideal though. I say kind of since the file I'm debugging might not be one I'm editing but from somewhere else in the codebase, so it's not trivial to make a change in it and rebuild with my own version – rbennett485 Nov 25 '15 at 11:30
0

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.

Aftnix
  • 4,461
  • 6
  • 26
  • 43