c++cgdb

gdb fails when checking conditions at breakpoints


I define a breakpoint by

b foo:124 if strcmp(bar::foo::getName(), "abc")==0

But gdb fails with the following errors

[Thread 0x7fffe8ef9700 (LWP 25817) exited]
[Switching to Thread 0x7fffdfc2f700 (LWP 25972)]
Error in testing breakpoint condition:
Couldn't get registers: No such process.
An error occurred while in a function called from GDB.
Evaluation of the expression containing the function
(bar::foo::getName() const) will be abandoned.
When the function is done executing, GDB will silently stop.
Selected thread is running.

Solution

  • b foo:124 if strcmp(bar::foo::getName(), "abc")==0

    Such a condition is Really Bad Idea(TM) for two reasons:

    1. If the application state is corrupted (even temporarily) and getName dereferences memory, it will likely crash, producing exactly the confusing output you've observed.
    2. In order for GDB to evaluate "abc", it must synthesize these bytes "inside" the program being debugged. It does this by synthesizing a call to strdup, and leaks the resulting memory. That can also terminate the program being debugged.

    Update:

    I found my program generates incorrect results for the element with name "abc". There are millions of elements. So I wanted to use gdb to stop at some code when the element name is "abc".

    There are few techniques you could use.

    The easiest is to insert this code into your program:

    const char *const name = getName();
    if (strcmp(name, "abc") == 0) {
      if (0) printf("here\n");  // set a breakpoint here 
    }
    

    The advantage here is: it's much faster for the program to evaluate the condition than it is for GDB. And instead of having GDB stop on every invocation of the routine that generates results, you only stop on "interesting" invocations (also much faster).

    The disadvantage is that you have to rebuild the program, and sometimes that makes the bug hide.

    Another possible technique is to examine the data that getName returns directly (instead of calling getName()) -- GDB can access private data. If getName looks like this:

    const char *getName() { return name_; }
    

    then you can re-formulate your condition like so:

    b foo.cc:124 if (name_[0] == 'a' && name_[1] == 'b' && name_[3] == 'c' && name_[4] == '\0')
    

    This eliminates both problems with your initial approach, but is a bit verbose.