What do a couple of curly braces mean in gdb print command? - gdb

Debug messages from gdb:
(gdb) p head_->next
$43 = { 0x0 }
(gdb) p (void *)head_->next
$44 = (void *) 0x603014
(gdb) p / head_->next
$45 = { 0x0 }
Please see the following screenshot:
head_->next is a member variable declared like:
int *next[3];
At first, I thought head_->next was a pointer. But actually it's not. Now I'm confused, what does "{0x0}" mean in gdb?

head_->next is a member variable declared like:
int *next[3];
No, it's not. At least not in that file. If it were declared like that, you would see this:
(gdb) p head_->next
$1 = {0x0, 0x0, 0x0}
Proof:
cat t.c
#include <stdlib.h>
struct Foo {
int *next[3];
};
int main()
{
struct Foo *head = calloc(1, sizeof(struct Foo));
return 0;
}
gcc -g t.c && gdb -q ./a.out
(gdb) start
(gdb) next
(gdb) p head->next
what does "{0x0}" mean in gdb?
It means that GDB believes that the entity being printed is an array of 1 element.
If you want to examine 3 elements from that array, you can do this:
(gdb) p head_->next[0]#3

Related

Extend stl-views.gdb with parray

I want to extend the stl-views.gdb with parray
How can I determine the size (N) of std::array in gdb?
#
# std::array<>
#
define parray
if $argc == 0
help parray
else
set $size = ???
..
Thanks for the help
Try using set $size = $arg0.size().
I have tested with the following code (where .size() is not used explicitly used).
#include <string>
#include <iostream>
#include <array>
int main() {
std::array<int, 3> arr {1,2,3};
std::cout << arr[0] << std::endl;
}
Then the following defined worked
define parray
if $argc == 0
help parray
else
set $size = $arg0.size()
print($size)
end
both with a running process or without a running process (debugging from a core file).
If calling .size() does not work for some reason then we need to see which internal variables of the array we can use. Using p /r arr we can see the arr variable without any pretty-printing. This shows something like
$5 = {
_M_elems = {[0] = 1,
[1] = 2,
[2] = 3}
}
in my machine (code was compiled with gcc 10), but it might be implementation-dependent. We can then try to get the size from _M_elems.
We can then try using the approach here to get the size. That is, using something such as
set $size = sizeof($arg0._M_elems) / sizeof(*$arg0._M_elems)
The gdb define code becomes
define parray
if $argc == 0
help parray
else
set $size = sizeof($arg0._M_elems) / sizeof(*$arg0._M_elems)
print($size)
end

How strtok_r function return values?

I am doing component test for a 'C' code. I have read the functionality of strtok_r function but I am not able to get the return value that I want to pass in strncmp' function. My code is contains strtok_r and strncmp functions as below:
typedef struct BufferN {
uint32_t v;
uint32_t m;
} My_Buffer;
char subsystemstr[64] = { '\0' };
My_Buffer buffer;
char *p_system;
char *p_subsystem;
(void) GetString(&buffer, subsystemstr, sizeof(subsystemstr));
p_system = strtok_r (subsystemstr, ":", &p_subsystem);
for (i = 0u; i < 100; i++)
{
if (strncmp(p_system, "all", 64) == 0)
{
/*Some Code Statement*/
}
}
Since array subsystemstr is initialized to '\0', I am modifying this array value with the help of function GetString as below:
strncpy(subsystemstr, "all:", 64);
When I am printing subsystemstr, I am having updated array as:
["all:", '\0' <repeats 59 times>]
but when I am printing p_system(return value of strtok_r). I am getting
[0x388870 ""]
I am confused how it is working. Actually I want value of p_system = "all" so that 'strncmp' function can return 0.
Please suggest.
I suspect your understanding of what
p p_system
actually does (prints the address of p_system)
in gdb, the command would be
p *p_system
or, using the builtin printf command
printf "%s", p_system
or, using the C function
call printf("%s", p_system)
or,
call (void)puts(p_system)
or, if you do not mind also seeing some address values
x /s p_system

GDB & C++: Printing vector of pointers to objects

In my code, I have a STL vector which holds pointers to objects.
The reason why I coded like this is because I must manipulate the objects itself from different places.
std::vector<Object*> objects;
for (int i = 0; i < 10; i++) {
Object* o = new Object(i);
objects.push_back(o);
}
This code is assuming that Object is an object which takes in an integer as a constructor parameter. Assuming that I breakpoint with my GDB after the for loop ends, what do I have to do in order to view the objects within my vector easily?
When I do "p objects" it only lists the pointer addresses which is totally expected, but I want to see the integer variable that each object holds as well. I tried "p objects[0]" but this returns "Could not find operator[]".
Has anyone ran into this problem? or know how I can get around this?
My goal is to be able to look inside what objects actually hold from GDB when those object's pointers are stored in a STL vector.
This is certainly implemented defined, but for GCC, you can do:
print **(v._M_impl._M_start)#1
Where v refers to the vector, and 1 refers to the index. You need to dereference twice to get the value.
struct Object
{
int n;
Object(int n)
: n(n) { }
};
int main()
{
std::vector<Object*> v;
v.push_back(new Object{42});
v.size(); // where we breakpoint
// release our memory at some point
}
And our test run:
(gdb) break 16
Breakpoint 1 at 0x400aae: file test.cpp, line 16.
(gdb) run
Starting program: a.out
Breakpoint 1, main () at test.cpp:16
16 v.size(); // where we breakpoint
(gdb) print v
$1 = {<std::_Vector_base<Object*, std::allocator<Object*> >> = {
_M_impl = {<std::allocator<Object*>> = {<__gnu_cxx::new_allocator<Object*>> = {<No data fields>}, <No data fields>}, _M_start = 0x604030, _M_finish = 0x604038, _M_end_of_storage = 0x604038}}, <No data fields>}
(gdb) print **(v._M_impl._M_start)#1
$2 = {{n = 42}}
Here is a function that prints the values one after another:
define pv
set $pvPOS_ = 0
while $arg0._M_impl._M_start + $pvPOS_ != $arg0._M_impl._M_finish
print **($arg0._M_impl._M_start + $pvPOS_)
set $pvPOS_ = $pvPOS_ + 1
end
end
Used as pv my_vec

Error on return after operating on a vector

I have a chunk of code:
void split(std::vector<std::string> * v,const char* s,const char* x) {
size_t len = strlen(s);
size_t slen = strlen(x); //slen = Search Length
if(len==0||slen==0)
return;
v->clear();
char* f = new char[len];
memset(f,0,len);
int * counter =new int;
(*counter)=0;
for(unsigned int i = 0; i<len; i++) {
if(isNext((s+(i*sizeof(char*))),x)) {
f[i]=1;
counter++;
}
}
if((*counter)==0) {
delete [] f;
delete counter;
v->clear();
return;
}
...
However when I am debugging it with gdb (on cygwin) or the visual studio debugger I get this error (from the cygwin console)
(gdb) step
36 if(len==0||slen==0)
(gdb) step
38 v->clear();
(gdb) step
std::vector<std::string, std::allocator<std::string> >::clear (
this=0x60003a3e0)
at /usr/lib/gcc/x86_64-pc-cygwin/4.8.2/include/c++/bits/stl_vector.h:1126
1126 { _M_erase_at_end(this->_M_impl._M_start); }
(gdb)
No matter where I compile it I get the same error! When I check the values of all the variables within gdb everything is correct (values are exactly what they should be). The vector does work because I intialize it in main(), use it and then delete it and reallocate it (all without issue). Am I missing some big thing here? Googling and debugging for hours didn't seem to bring up anything. Any help is appreciated!
There's a lot here that can be simplified, but as far as major problems there is this:
int * counter =new int;
(*counter)=0;
counter++;
The counter++ is incrementing the pointer not the value pointed to. I don't see any reason why this needs to be a pointer and should probably be avoided as it just adds complexity to this.
What does isNext do? There definitely a lot you can do to simply this and when that's done it will likely reduce problems.
What are you passing to split? If the vector is uninitialized the call to ->clear() could cause an access violation.

Segmentation fault(core dumped) - while accessing member of a structure through an object

I got a segmentation fault(core dumped) error and tried debugging using gdb. I found out where the error occurred:
Program received signal SIGSEGV, Segmentation fault.
0x08048edb in state_update2 () at xxx.cpp:333
333 if (rob.head->is_complete == 1 && rob.head->ready_to_retire == 1 )
A few lines of the code are:
if(rob.head->is_complete == 1 && rob.head->ready_to_retire == 1) {
reorder_buffer_node *temp = new reorder_buffer_node[sizeof(struct reorder_buffer_node)];
temp = rob.head;
for(uint64_t i=0; i<f_; i++) {
if(temp->is_complete == 1 && temp->ready_to_retire == 1) {
rob.pop();
retired_inst++;
temp = temp->next;
}
else break;
}
}
ROB is a cyclic queue and head is a pointer to a structure which is of the form:
struct reorder_buffer_node {
int is_complete;
uint64_t instr_num;
uint64_t dest_reg;
uint64_t index;
reorder_buffer_node *next;
int ready_to_retire;
};
Am I not accessing the members of the structure in the right way? Please let me know!
reorder_buffer_node *temp = new reorder_buffer_node[sizeof(struct reorder_buffer_node)];
//Are you trying to create an array of reorder_buffer_node and name as temp??
temp = rob.head;
//With the above comment this line will not happen
temp = temp->next;
//You have not written any constructor for the structure, hence with default constructor, it temp will be assigned to garbage or NULL. When you do the above step it might provide segmentation fault or crash. So better to write a constructor.
If following steps taken care of it will run correctly.
I don't have enough context to say for sure but I would start with these two lines:
reorder_buffer_node *temp = new reorder_buffer_node[sizeof(struct reorder_buffer_node)];
temp = rob.head;
Which destroy the value of the new in a way similar to:
int temp = 15;
temp = 5;
If I understand you correctly crash happens at if()? So, as you mentioned that head is a pointer, then maybe it is not allocated? If so following code gives a segmentation fault:
if(rob.head->is_complete == 1 && rob.head->ready_to_retire == 1)
To check it you can just a print out pointer or add check for NULL for this pointer.