gdb 打印 long 值,观察用 rand() 设置的变量
gdb prints long values watching a variable set with rand()
我正在使用 gdb
脚本来观察变量的变化 awatch
:
#!/bin/bash
# Compile
gcc -Wall -pedantic -g -o demo demo.c
# Exit on compile error
if [ $? -ne 0 ]; then
exit
fi
# Overwrite the contents of trace.gdb with a title
echo "# Watch var" > trace.gdb
# Don't stop each time there is a pagination
echo "set pagination off" >> trace.gdb
# Set a breakpoint in order to read the var address
echo "break main" >> trace.gdb
# Run the debugger
echo "run" >> trace.gdb
# Set watchpoint
echo "awatch var" >> trace.gdb
# Don't stop on each watchpoint (just show the trace)
echo "commands" >> trace.gdb
echo "continue" >> trace.gdb
echo "end" >> trace.gdb
# Start monitoring
echo "continue" >> trace.gdb
# Exit the debugger
echo "quit" >> trace.gdb
# Run the generated script
gdb -quiet -command=trace.gdb demo
程序:
/* demo.c */
#include <stdio.h>
int main(void)
{
int var = 0;
for (int i = 0; i < 5; i++)
{
var++;
}
printf("%d\n", var);
return 0;
}
输出似乎正确:
Hardware access (read/write) watchpoint 2: var
Value = 0
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 0
New value = 1
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 1
New value = 2
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 2
New value = 3
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 3
New value = 4
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 4
New value = 5
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Value = 5
0x0000555555555176 in main () at demo.c:11
11 printf("%d\n", var);
5
但是如果我使用 rand()
切换到此代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int var = 0;
srand((unsigned)time(NULL));
for (int i = 0; i < 10; i++)
{
var = rand() % 10;
}
printf("%d\n", var);
return 0;
}
和运行相同的脚本,gdb
开始打印错误的值:
Breakpoint 1, main () at demo.c:6
6 {
Hardware access (read/write) watchpoint 2: var
Hardware access (read/write) watchpoint 2: var
Value = 0
main () at demo.c:9
9 srand((unsigned)time(NULL));
Hardware access (read/write) watchpoint 2: var
Old value = 0
New value = 32015002
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 32015002
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 32015002
New value = 7
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 7
New value = 84992124
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 84992124
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 84992124
New value = 6
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 6
New value = 55442740
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 55442740
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 55442740
New value = 0
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 0
New value = 208731384
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 208731384
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 208731384
New value = 3
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 3
New value = 114916873
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 114916873
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 114916873
New value = 9
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Value = 9
0x0000555555555216 in main () at demo.c:14
14 printf("%d\n", var);
9
我已经阅读了这个 post:gdb prints wrong values when modifying arguments 并使用 -fvar-tracking
进行了编译,但它没有帮助。
为什么 rand()
会出现这种行为?
未优化的 gcc 程序集可能很奇怪:
jmp .L2
.L3:
call rand
movl %eax, %edx
movslq %edx, %rax
imulq 17986919, %rax, %rax
shrq , %rax
sarl , %eax
movl %edx, %ecx
sarl , %ecx
subl %ecx, %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %ecx
movl %ecx, %eax
sall , %eax
addl %ecx, %eax
addl %eax, %eax
subl %eax, %edx
movl %edx, -4(%rbp)
addl , -8(%rbp)
.L2:
cmpl , -8(%rbp)
jle .L3
而且您似乎在等待 -4(%rbp)
。所以 movl %eax, -4(%rbp)
放了一个“大数字”,然后读入 movl -4(%rbp), %ecx
然后 movl %edx, -4(%rbp)
放了 % 10
的结果。所以你从计算的中间看到了一些数字。 IE。一圈对应:
New value = 32015002
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 32015002
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 32015002
New value = 7
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
我正在使用 gdb
脚本来观察变量的变化 awatch
:
#!/bin/bash
# Compile
gcc -Wall -pedantic -g -o demo demo.c
# Exit on compile error
if [ $? -ne 0 ]; then
exit
fi
# Overwrite the contents of trace.gdb with a title
echo "# Watch var" > trace.gdb
# Don't stop each time there is a pagination
echo "set pagination off" >> trace.gdb
# Set a breakpoint in order to read the var address
echo "break main" >> trace.gdb
# Run the debugger
echo "run" >> trace.gdb
# Set watchpoint
echo "awatch var" >> trace.gdb
# Don't stop on each watchpoint (just show the trace)
echo "commands" >> trace.gdb
echo "continue" >> trace.gdb
echo "end" >> trace.gdb
# Start monitoring
echo "continue" >> trace.gdb
# Exit the debugger
echo "quit" >> trace.gdb
# Run the generated script
gdb -quiet -command=trace.gdb demo
程序:
/* demo.c */
#include <stdio.h>
int main(void)
{
int var = 0;
for (int i = 0; i < 5; i++)
{
var++;
}
printf("%d\n", var);
return 0;
}
输出似乎正确:
Hardware access (read/write) watchpoint 2: var
Value = 0
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 0
New value = 1
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 1
New value = 2
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 2
New value = 3
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 3
New value = 4
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 4
New value = 5
main () at demo.c:7
7 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Value = 5
0x0000555555555176 in main () at demo.c:11
11 printf("%d\n", var);
5
但是如果我使用 rand()
切换到此代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int var = 0;
srand((unsigned)time(NULL));
for (int i = 0; i < 10; i++)
{
var = rand() % 10;
}
printf("%d\n", var);
return 0;
}
和运行相同的脚本,gdb
开始打印错误的值:
Breakpoint 1, main () at demo.c:6
6 {
Hardware access (read/write) watchpoint 2: var
Hardware access (read/write) watchpoint 2: var
Value = 0
main () at demo.c:9
9 srand((unsigned)time(NULL));
Hardware access (read/write) watchpoint 2: var
Old value = 0
New value = 32015002
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 32015002
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 32015002
New value = 7
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 7
New value = 84992124
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 84992124
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 84992124
New value = 6
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 6
New value = 55442740
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 55442740
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 55442740
New value = 0
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 0
New value = 208731384
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 208731384
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 208731384
New value = 3
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Old value = 3
New value = 114916873
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 114916873
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 114916873
New value = 9
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var
Value = 9
0x0000555555555216 in main () at demo.c:14
14 printf("%d\n", var);
9
我已经阅读了这个 post:gdb prints wrong values when modifying arguments 并使用 -fvar-tracking
进行了编译,但它没有帮助。
为什么 rand()
会出现这种行为?
未优化的 gcc 程序集可能很奇怪:
jmp .L2
.L3:
call rand
movl %eax, %edx
movslq %edx, %rax
imulq 17986919, %rax, %rax
shrq , %rax
sarl , %eax
movl %edx, %ecx
sarl , %ecx
subl %ecx, %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %ecx
movl %ecx, %eax
sall , %eax
addl %ecx, %eax
addl %eax, %eax
subl %eax, %edx
movl %edx, -4(%rbp)
addl , -8(%rbp)
.L2:
cmpl , -8(%rbp)
jle .L3
而且您似乎在等待 -4(%rbp)
。所以 movl %eax, -4(%rbp)
放了一个“大数字”,然后读入 movl -4(%rbp), %ecx
然后 movl %edx, -4(%rbp)
放了 % 10
的结果。所以你从计算的中间看到了一些数字。 IE。一圈对应:
New value = 32015002
0x00005555555551f8 in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Value = 32015002
0x00005555555551fb in main () at demo.c:12
12 var = rand() % 10;
Hardware access (read/write) watchpoint 2: var
Old value = 32015002
New value = 7
main () at demo.c:10
10 for (int i = 0; i < 5; i++)
Hardware access (read/write) watchpoint 2: var