struct field name conflict with stl array in GDB - c++

#include <array>
typedef struct {
int array;
} tp1;
int main()
{
std::array<int,8> array1;
/*int array=0;*/
/*array ++;*/
tp1 v1;
v1.array = 2;
return 0;
}
When struct has field "array" and the code uses std::array, it seems the 2 "array" are conflicted in gdb. I get syntax error in printing v1.array:
Temporary breakpoint 1, main () at a2.c:12
12 v1.array = 2;
(gdb) n
13 return 0;
(gdb) p v1.array
A syntax error in expression, near `'.
But if I add a local variable "array", it then works fine.
(gdb) p array
$1 = 1
(gdb) p v1.array
$2 = 2
std::array should be in namespace std, and not related to field name. Not sure why it gets confused.
Any suggestion to print v1.array without the local variable?

Not sure why it gets confused.
This is (was?) surely a bug in GDB.
It does not reproduce when using GDB 10.0 on x86_64, while compiling with g++ (Debian 9.3.0-8):
Temporary breakpoint 1, main () at t.cc:12
12 v1.array = 2;
(gdb) n
13 return 0;
(gdb) p v1.array
$1 = 2
Try newer GDB version?

Related

How to view the internal data of a smart pointer inside gdb?

I've got test program like below:
#include<memory>
#include<iostream>
using namespace std;
int main()
{
shared_ptr<int> si(new int(5));
return 0;
}
Debug it:
(gdb) l
1 #include<memory>
2 #include<iostream>
3 using namespace std;
4
5 int main()
6 {
7 shared_ptr<int> si(new int(5));
8 return 0;
9 }
10
(gdb) b 8
Breakpoint 1 at 0x400bba: file testshare.cpp, line 8.
(gdb) r
Starting program: /home/x/cpp/x01/a.out
Breakpoint 1, main () at testshare.cpp:8
8 return 0;
(gdb) p si
$1 = std::shared_ptr (count 1, weak 0) 0x614c20
It only prints out the pointer type information of si, but how to get the value stored in it (in this case 5)?
How can I check the internal content of si during debugging?
Try the following:
p *si._M_ptr
Now, this assumes that you're using libstdc++.so, given the output for p si.
Alternatively, you could use the value 0x614c20 directly (from your output):
p {int}0x614c20
Both should display the value 5.
but how to get the value stored in it
You will have to cast raw pointer to actual pointer type stored in std::shared_ptr. Use whatis to know what the actual pointer type is.
(gdb) p si
$8 = std::shared_ptr (count 1, weak 0) 0x614c20
(gdb) whatis si
type = std::shared_ptr<int>
(gdb) p *(int*)0x614c20
$9 = 5

gdb cannot index into an array and print value

I have an object a of type vector<char>. I know it is 10 elements long. But, when I do p a[5] in gdb, I get an error saying gdb could not resolve symbol operator[].
void foo()
{
vector<char> a (10, 10); // put a breakpoint here.
}
Could you please suggest me a way to print the value at index in gdb? Right now, I did something really lame -
char c1=a[1]; char c2 = a[2]; char c3 = a[3]; // ... so on and forth
Can I trust the values in c1, c2, etc
P.S. I have built my code with DEBUG symbols.
A vector is not the same as an array or a pointer. A vector typically has a pointer to the start, which you can use to access elements. Try something like this
p *(a._M_impl._M_start+5)
Here I'm accessing the pointer to the start of the array, adding 5 to get the element at index 5.
This works without issues with gdb 7.11.1
(gdb) b main
Breakpoint 1 at 0x400bd3: file t.C, line 6.
(gdb) run
Starting program: /tmp/t
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.23.1-8.fc24.x86_64
Breakpoint 1, main () at t.C:6
6 std::vector<char> a={'a','b','c','d','e','f'};
Missing separate debuginfos, use: dnf debuginfo-install libgcc-6.1.1-3.fc24.x86_64 libstdc++-6.1.1-3.fc24.x86_64
(gdb) n
8 std::cout << "Ok" << std::endl;
(gdb) p a
$1 = std::vector of length 6, capacity 6 = {97 'a', 98 'b', 99 'c', 100 'd',
101 'e', 102 'f'}
(gdb) p a[2]
$2 = 99 'c'
The answer here is to update to the current version of gcc and gdb.

unexpected results for memory allocation with c malloc function

I have to allocate memory for 4 pointers to pointers on float (2D) over many iterations (6), but at the second iteration, malloc gives me the same address for two allocations. Code :
int i=0, a=0;
for(i=0;i<6;i++)
{
float** P_i=(float**) malloc(4*sizeof(float*));
for(a=0;a<4;a++) P_i[a]=(float*) calloc(4,sizeof(float));
for(a=0;a<4;a++) free(P_i[a]);
free(P_i);
}
Debugging with gdb :
(gdb) print i
$42 = 1
(gdb) set $pos=0
(gdb) print P_i[$pos++]
$51 = (float *) 0x804d500
(gdb) print P_i[$pos++]
$52 = (float *) 0x804d148
(gdb) print P_i[$pos++]
$53 = (float *) 0x804d4e8
(gdb) print P_i[$pos++]
$54 = (float *) 0x804d500
P_i[0] and P_i[3] point to the same address 0x804d500 and I can't find why :/
between the first for(a=0;a<4;a++) and the 2nd (before freeing)
My guess is that gdb breaks on last iteration of the loop, before the last calloc() call. If it's the case P_i[3] have the address of the previous iteration.
Btw, it's hard to use gdb when there's more than one statement per line.
With information available this can't be answered, but let me try.
The code seems ok. I can't reproduce your problem either.
You can't really put a breakpoint on a blank line. I guess that would put it on a line with free.
My guess is, your code was compiled with optimization enabled, which probably reordered things making sure you are not really sure where execution has stopped. Disable optimization and re-build (on GCC that would be -O0). Or show us the disassembly (including current PC where you print).
My run on Ubuntu gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4 built with -O0 -g, stopped on a line with free (before it was executed):
(gdb) print i
$1 = 0
(gdb) set $pos=0
(gdb) print P_i[$pos++]
$2 = (float *) 0x602040
(gdb) print P_i[$pos++]
$3 = (float *) 0x602060
(gdb) print P_i[$pos++]
$4 = (float *) 0x602080
(gdb) print P_i[$pos++]
$5 = (float *) 0x6020a0
(gdb) bt
#0 main () at malloc.c:12
(gdb) list
7 for(i=0;i<6;i++)
8 {
9 float** P_i=(float**) malloc(4*sizeof(float*));
10 for(a=0;a<4;a++) P_i[a]=(float*) calloc(4,sizeof(float));
11
12 for(a=0;a<4;a++) free(P_i[a]);
Does your source code exhibit a problem even if you build it separately (not a part of larger program)? Do you have custom calloc / malloc implemented? What does "nm your-executable|grep calloc" show? It should be something like this:
U calloc##GLIBC_2.2.5

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

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]"?
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
The order of evaluating "*vecIter == vec[1]" is evaluating *vecIter first, if true then skip evaluating vec[1] and the whole statement is true; and if false then evaluate vec[1]. The root cause here is that vecIter pointing to NULL memory, which is inaccessible, that *vecIter could not even be evaluated. Therefore gdb print out the "memory access" error.
same reason for other print statements of same error

Is there a gdb especially for c++? [duplicate]

Supposing to have something like this:
#include <map>
int main(){
std::map<int,int> m;
m[1] = 2;
m[2] = 4;
return 0;
}
I would like to be able to inspect the contents of the map running the program from gdb.
If I try using the subscript operator I get:
(gdb) p m[1]
Attempt to take address of value not located in memory.
Using the find method does not yield better results:
(gdb) p m.find(1)
Cannot evaluate function -- may be inlined
Is there a way to accomplish this?
The existing answers to this question are very out of date. With a recent GCC and GDB it Just WorksTM thanks to the built-in Python support in GDB 7.x and the libstdc++ pretty printers that come with GCC.
For the OP's example I get:
(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}
If it doesn't work automatically for you see the first bullet point on the STL Support page of the GDB wiki.
You can write Python pretty printers for your own types too, see Pretty Printing in the GDB manual.
I think there isn't, at least not if your source is optimized etc. However, there are some macros for gdb that can inspect STL containers for you:
http://sourceware.org/ml/gdb/2008-02/msg00064.html
However, I don't use this, so YMMV
There's always the obvious: Define your own test-function... Call it from gdb. E.g.:
#define SHOW(X) cout << # X " = " << (X) << endl
void testPrint( map<int,int> & m, int i )
{
SHOW( m[i] );
SHOW( m.find(i)->first );
}
int
main()
{
std::map<int,int> m;
m[1] = 2;
m[2] = 4;
return 0; // Line 15.
}
And:
....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD
Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb)
The stl-views.gdb used to be the best answer there was, but not anymore.
This isn't integrated into the mainline GDB yet, but here is what you get using the 'archer-tromey-python' branch:
(gdb) list
1 #include <map>
2 int main(){
3 std::map<int,int> m;
4 m[1] = 2;
5 m[2] = 4;
6 return 0;
7 }
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run
Breakpoint 1, main () at map.cc:6
6 return 0;
(gdb) print m
$1 = std::map with 2 elements = {
[1] = 2,
[2] = 4
}
(gdb) quit
Try De-Referencing STL Containers: on this page: http://www.yolinux.com/TUTORIALS/GDB-Commands.html
The answers above are working and fine. In case you are using stl-views.gdb, here is the proper way of viewing the maps and elements inside it.
Let your map is as follows :
std::map<char, int> myMap;
(gdb) pmap myMap char int
i.e. pmap <variable_name> <left_element_type> <right_element_type> to see the elements in the map.
Hope that helps.
You can get around the second problem (Cannot evaluate function -- may be inlined) by making sure that your compiler uses DWARF-2 (or 3 or 4) debugging information when you compile your program. DWARF-2 includes inlining information, so you should be able to use either of the methods you described to access elements of your std::map container.
To compile with DWARF-2 debug info, add the -gdwarf-2 flag to your compile command.