sizeof reference to array in gdb - c++

int main()
{
typedef unsigned char a4[4];
a4 p1;
a4& p2 = p1;
p2[1]=1;
cout<<sizeof(p2);
return p2[1];
}
Compile, start gdb and put breakpoint on return. If you type p sizeof(p2), gdb will print 8 instead of 4 which will be printed if you start the program. If you write in gdb p sizeof(*p2), the output is 4 (the size of array). I think this is because gdb treats p2 as pointer(reference is implemented behind the scene as pointer).
Tested with compilers GCC 4.8.2 and Clang 4.3 on GDB 7.7 linux arch., ubuntu 13.10,
Is this correct or a bug in gdb?

Here's a modified version of your program. I've changed the array size from 4 to 17 to ensure that its size is distinguishable from anything else. I've also changed the type and variable names to make the code easier to follow, and added #include <iostream> so it actually compiles. I've also removed some unnecessary stuff.
#include <iostream>
int main()
{
typedef unsigned char char17[17];
char17 arr17;
char17& arr17_ref = arr17;
std::cout << "sizeof(arr17) = "
<< sizeof arr17
<< ", sizeof(arr17_ref) = "
<< sizeof(arr17_ref)
<< "\n";
return 0;
}
When I compile and run it on my system, the output is 17.
When I run it under gdb, I get 8 (the size of a pointer on my system):
$ gdb ./c
GNU gdb (GDB) 7.5-ubuntu
[snip]
Reading symbols from /home/kst/c...done.
(gdb) b 12
Breakpoint 1 at 0x40097e: file c.cpp, line 12.
(gdb) r
Starting program: /home/kst/c
sizeof(arr17) = 17, sizeof(arr17_ref) = 17
Breakpoint 1, main () at c.cpp:12
12 return 0;
(gdb) p sizeof(arr17)
$1 = 17
(gdb) p sizeof(arr17_ref)
$2 = 8
(gdb) c
Continuing.
[Inferior 1 (process 23420) exited normally]
(gdb) q
$
Yes, this is a bug in gdb. gdb is supposed to evaluate expressions as they'd be evaluated in a running program; in this case, it fails to do so.
(I'm using gcc 4.7.2 and gdb 7.5 on Linux Mint 14.)
UPDATE :
The OP submitted a bug report: https://sourceware.org/bugzilla/show_bug.cgi?id=16675
and it's been fixed. The patch was approved and committed 2014-04-14. I still see the bug in gdb 7.7.1, but it's fixed in 7.11.1.

Related

Weird behaviour of GDB

I've been trying to debug a little thingie, and almost went insane while trying to do so. After several hours of figuring out the problem, I finally have a snippet of code that is the root of my problem:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main()
{
std::vector<int> foo = std::vector<int>();
foo.push_back(0);
foo.push_back(11);
foo.push_back(222);
foo.push_back(3333);
std::stack<int> bar = std::stack<int>();
cout << endl << foo.size() << endl << endl;
return 0;
}
With this compiled, using:
g++ -std=c++11 -ggdb -O0 -pedantic -Wall -Wextra -Wno-nonnull -fkeep-inline-functions
I then try the following:
(gdb) br 18
Breakpoint 1 at 0x40170c: file ./....cpp, line 18.
(gdb) r
Starting program: ...
[New Thread 15620.0x3c3c]
Breakpoint 1, main () at ./....cpp:18
18 cout << endl << foo.size() << endl << endl;
(gdb) p foo.size()
$1 = 4293588256
(gdb) c
Continuing.
4
[Inferior 1 (process 15620) exited normally]
(gdb)
Apparenly, 4 is now equal to 4293588256. What the bloody hell is going on?
Also, if I break the program before the stack is created, GDB shows the size properly.
EDIT:
I am on windows 8.1, versions of stuffs are: G++ 4.8.1; GDB 7.6.1
Turns out this really is a problem of either GDB 7.6.1 or G++ 4.8.1.
Updating GDB to 7.8.1 and G++ to version 4.9.2 solved the problem.

Where to put HW BP to catch the global variable address corruption?

Program in C/C++ runs on embedded PowerPC under debugger with HW break points capabilities.
There is global variable 'char Name[256]' known in 2 files and 2 tasks correspondingly. One task reads Name, another fills it with a text, '1234567...', for example.
At some moment, global variable Name gets corrupted. When asked for the variable address gdb shows (and application prints by debug printouts) address equal to 0x31323334.
How to catch this bug with HW breakpoints? I mean at what address to put HWBP.
When I look into assembler, I see:
lis 9,Name#ha
lwz 9,Namel#l(9)
So, how memory corruption can change the code without influencing the application flow - it should crash immediately, no?
Thanks a lot ahead
0x31323334 is "1234" sans null terminator. Further, "Global variable address corruption" does not make much sense "global variables" (whose addresses do not change), nor really for an array of size 256 (unless you're using a pointer somewhere and it's the pointer which is being corrupted). So I suspect you might be unfamiliar with GDB.
When using GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 on x86 (admittedly, not ppc, but basically the same software) with the following test file:
// g++ test.cpp -g
#include <iostream>
char Name[256] = "123456789";
int main() {
Name[0] = 'a';
std::cout << Name << std::endl;
}
I can get the following output from GDB:
(gdb) break main
Breakpoint 2 at 0x40086a: file test.cpp, line 6.
(gdb) r
Starting program: /home/keithb/dev/mytest/a.out
Breakpoint 2, main () at test.cpp:6
6 Name[0] = 'a';
(gdb) whatis Name
type = char [256]
(gdb) print Name
$1 = "123456789", '\000' <repeats 246 times>
(gdb) print &Name
$2 = (char (*)[256]) 0x6010c0 <Name>
In any case, if you really do want to set a "hardware breakpoint" (GDB calls those "watchpoints"), then you can do get the address of Name prior to corruption. Then just set the watchpoint and wait for your program to write to the address.
(gdb) c
Continuing.
a23456789
[Inferior 1 (process 21878) exited normally]
(gdb) delete 2
(gdb) watch *0x6010c0
Hardware watchpoint 3: *0x6010c0
(gdb) r
Starting program: /home/keithb/dev/mytest/a.out
Hardware watchpoint 3: *0x6010c0
Old value = 875770417
New value = 875770465
main () at test.cpp:7
7 std::cout << Name << std::endl;
(gdb)

C++ gdb print array gives No symbol "d" in context

I am trying to debug a C++ program but I face the below issue when trying to print the contents of the array.
I have declared a array of chars as below in the c++ program
using namespace std;
int main() {
string s;
cin >> s;
char d[s.size()];
int i=0;
int j=0;
while(j<s.size()) {
if(s[j] != '+') {
d[i++] = s[j];
}
j++;
}
}
I use the below commands to compile the above code and run gdb
g++ -g main.cpp -o main
gdb main
However when I debug and hit the below command in GDB I get the below error.
Command entered in GDB : p *d#10
No symbol "d" in current context.
Can you please let me know what I can do so that all the contents of the array is printed?
Until you run the program, there are no variables to print. For your program, you should set a breakpoint at the last line of main, and run the program. When the program stops at the breakpoint, you can then print d.
(gdb) list 15
10 while(j<s.size()) {
11 if(s[j] != '+') {
12 d[i++] = s[j];
13 }
14 j++;
15 }
16 }
(gdb) break 15
Breakpoint 1 at 0x80488b9: file x.cc, line 15.
(gdb) run
Starting program: /home/jxh/StackOverflow/gdb/a.out
1234567890
Breakpoint 1, main () at x.cc:15
15 }
(gdb) p *d#10
$2 = "1234567890"
(gdb)
Make sure to turn off compiler optimizations. This link gives a little more detail.

gdb: break when a particular object is altered

I have an object defined in c++ with a pointer to it used in various functions and files throughout the project. I am having an issue with the data being updated, so I want to debug it to see what is happening. Ideally, I want to break every time the object is accessed. however, watch requires a specific memory address. So, for example, if I have:
class data{
public:
int a;
int b;
};
then gdb will only break when a is altered, since the pointer to data is pointed at a, but not when b is altered.
Is there a way to break whenever the entire range of memory covered by the data class is altered?
Is there a way to break whenever the entire range of memory covered by the data class is altered?
Perhaps.
GDB hardware watchpoints use special debug registers in hardware, and there is usually a limit on how such registers work. On x86, you can set up to 4 word-sized hardware watch points, so for example you gave you can set watchpoints on &data->a and &data->b, and that will "cover" entire memory of the data.
I am guessing that your actual data has many more members though, and so 4 word-sized watch points will not suffice.
If you are on platform which has Valgrind support, and if your program can execute under Valgrind, then you can use Valgrind's built-in gdbserver to set watchpoints on arbitrary regions of memory.
Update:
I looked through the page you linked to and couldn't find what I was looking for
I am not sure what you were looking for. Here is a sample session showing how it works:
#include <stdlib.h>
void foo(char *p)
{
*p = 'a';
}
typedef struct {
char buf[1024];
} data;
int main()
{
data *d = calloc(1, sizeof(data));
foo(d->buf + 999);
}
gcc -g main.c
valgrind --vgdb-error=0 ./a.out
...
==10345== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==10345== /path/to/gdb ./a.out
==10345== and then give GDB the following command
==10345== target remote | vgdb --pid=10345
... Valgrind now waits for debugger to attach.
In another window:
gdb ./a.out
GNU gdb (GDB) 7.4
...
(gdb) target remote | vgdb --pid=10345
relaying data between gdb and process 10345
[Switching to Thread 10345]
0x0000000004000af0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) b main
Breakpoint 1 at 0x40053d: file main.c, line 14.
(gdb) c
Breakpoint 1, main () at main.c:14
14 data *d = calloc(1, sizeof(data));
(gdb) n
15 foo(d->buf + 999);
(gdb) watch *d
Hardware watchpoint 2: *d
Note that a "hardware" watchpoint has been set on entire *d.
It's a hardware watchpoint only in the sense that Valgrind is the hardware.
(gdb) p d.buf[999]
$1 = 0 '\000'
(gdb) c
Hardware watchpoint 2: *d
Old value = {buf = '\000' <repeats 1023 times>}
New value = {buf = '\000' <repeats 999 times>, "a", '\000' <repeats 23 times>}
foo (p=0x51b6457 "a") at main.c:6
6 }
(gdb) q
Voila: the debugger stopped when 999th element was modified, proving that the watchpoint "covered" the entire structure.

Why does gdb show two different returns?

Last week I was a debugging a code and a weird situation came up: gdb passes through two different return clauses. I made a simple example that illustrates the situation:
#include <iostream>
using namespace std;
int test() {
string a = "asd";
string b = "asd";
while (true) {
if (a == b) {
return 0;
}
}
return -1;
}
int main() {
int result = test();
cout << "result: " << result << endl;
}
When debugging the code I got:
(gdb) b main
Breakpoint 1 at 0x1d4c: file example.cpp, line 19.
(gdb) r
Starting program: /Users/yuppienet/temp/a.out
Reading symbols for shared libraries +++. done
Breakpoint 1, main () at example.cpp:19
19 int result = test();
(gdb) s
test () at example.cpp:7
7 string a = "asd";
(gdb) n
8 string b = "asd";
(gdb) n
11 if (a == b) {
(gdb) n
12 return 0;
(gdb) n
15 return -1;
(gdb) n
16 }
(gdb) n
main () at example.cpp:20
20 cout << "result: " << result << endl;
(gdb) n
result: 0
21 }
(gdb) n
0x00001ab2 in start ()
I noted that even if gdb shows line 15, the return value is 0 (the finish command confirms this as well).
So the question is: why does gdb show line 15: return -1, even if the function is not really returning this value?
Thanks!
Edit:
I forgot to mention that I compiled with the following line:
g++ -Wall -pedantic -g -pg example.cpp
I suspect you're seeing the function epilogue. Your two strings have destructors, which are being implicitly called on return. Check out what the disassembly says to be sure, but I suspect that both return statements are mapping to something along the lines of:
stash return_value;
goto epilogue;
and correspondingly:
epilogue:
destroy a; // on the stack, so destructor will be called
destroy b;
really_return(stashed value);
The epilogue appears to come from line 15 as a side-effect of how g++ does line numbering - a fairly simple format, really just a list of tags of the form "address X comes from line number Y" - and so it's reporting 15 as the closest match. Confusing in this case, but correct a lot of the time.
Probably because the program counter register passes through the instructions that best map to the final return, i.e. the function's exit sequence. The actual return value is probably kept in a register, so the first return just loads the proper value and jumps to the end of the function, and then that address is "back-mapped" to the source code line of the final return.
You don't say, but if you compiled with optimization that is exactly the kind of behavior you would see in gdb. You see the first line setting up the return value, and then it jumps to the real return instruction but in C++ you see the entire thing including the return value.