Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't gdb evaulate functions when !=/== and &&/|| are combined in an expression?

Tags:

c++

gdb

It may be that the difficulty I'm having in describing my problem is the reason I can't find anyone else with an instance of it. I am using gdb 7.4-2012.04.

It seems at the least that any expression involving both !=/== and &&/|| for vectors or vector iterators will fail to evaluate in gdb with the following error:

Cannot access memory at address 0x0

Here's a test case, followed by my compilation line and tests:

#include <stdio.h>
#include <iostream>
#include <stdint.h>
#include <vector>

using namespace std;

typedef char GUID[32];

int main(int argc, char **argv){
    vector<int> vec;
    for (int i=0; i<5; i++){
        vec.push_back(i);
    }
    for (vector<int>::iterator vecIter=vec.begin(); vecIter!=vec.end(); vecIter++){
        int i=0;//Just need a line gdb will recognize for a breakpoint.
    }
    cout << vec[0] << endl;//g++ needs to include operator[] in the binary for this to work.
    return 0;
}

Here's a snippet of the tests I performed:

user@comp$ g++ -g -O0 any_test.cpp
user@comp$ gdb a.out
(gdb) b 16
(gdb) r
Breakpoint 1, main (argc=1, argv=0x7fffffffe288) at any_test.cpp:16
16          int i=0;//Just need a line gdb will recognize for a breakpoint.
(gdb) p *vecIter == vec[1] or *vecIter == vec[2]
Cannot access memory at address 0x0

The original useful statement does not work. Let's reduce a bit and find the problem.

(gdb) p vec[1] or *vecIter == vec[2]
Cannot access memory at address 0x0
(gdb) p vec[1] or *vecIter
$1 = true
(gdb) p 1 or *vecIter == vec[2]
Cannot access memory at address 0x0

Looks like the problem is '==' after 'or'. Is this the same with other operators?

(gdb) p 1 and *vecIter == vec[2]
Cannot access memory at address 0x0
(gdb) p 1 and *vecIter != vec[2]
Cannot access memory at address 0x0

That's a resounding yes. What if I pull out all the functions for gdb? Just let it dereference and compare ints?

(gdb) p 1 or *vecIter._M_current == vec._M_impl._M_start[1]
$2 = true

Ok, let's check some combinations of derefs and functions to make sure it's not just one of these types that causes the problem:

(gdb) p 1 or *vecIter._M_current == *vecIter
Cannot access memory at address 0x0
(gdb) p 1 or vec._M_impl._M_start[1] == vec[1]
Cannot access memory at address 0x0

As you can see, the problem is not specifically the vector or its iterator. Any operator (function) called on either one will trigger this issue if inserted after &&/||, and on either side of an ==/!=.

EDIT: forgot a question again. My question is this: Why do I get "Cannot access memory at address 0x0" in the line "p *vecIter == vec[1] or *vecIter == vec[2]"?

like image 917
longbowrocks Avatar asked Oct 21 '22 20:10

longbowrocks


1 Answers

The problem is in functions that return references. Here's a minimal example:

int& g() { static int i; return i; }
int main() {}

The same problem is exhibited (I'm using gdb 7.8.1):

(gdb) p 0 || +g()
Cannot access memory at address 0x0

A workaround is to convert the reference to a pointer and indirect it:

(gdb) p 0 || +*&g()
$1 = true

Filed a bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17904

like image 154
ecatmur Avatar answered Nov 15 '22 07:11

ecatmur