程序正常崩溃但 Valgrind 不会
Program crashes normally but not with Valgrind
我正在尝试调试一段汇编程序 (x86 64-bit
),根据 gdb
信息,使用以下指令时它崩溃了:
xorpd 0x1770(%rip),%xmm12 # 0x40337c <S_0x403230>
然而,在我看来,内存 0x40337c
是完全正常的:
(gdb) x /10x 0x40337c
0x40337c <S_0x403230>: 0x00000000 0x80000000 0x00000000 0x00000000
0x40338c <S_0x403240>: 0xf149f2ca 0x00000000 0x746e7973 0x203a7861
0x40339c <S_0x403248+8>: 0x206d626c 0x6d69743c
另一个有线的事情是,当我在命令行中以及在 gdb
中 运行 时,这段代码每次都会崩溃。但是,当我在 valgrind
中调试它时,它不会崩溃!
☁ src [master] ⚡ valgrind ./a.out 20 reference.dat 0 1 100_100_130_cf_a.of
==18329== Memcheck, a memory error detector
==18329== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==18329== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==18329== Command: ./a.out 20 reference.dat 0 1 100_100_130_cf_a.of
==18329==
MAIN_printInfo:
grid size : 100 x 100 x 130 = 1.30 * 10^6 Cells
nTimeSteps : 20
result file : reference.dat
action : nothing
simulation type: channel flow
obstacle file : 100_100_130_cf_a.of
LBM_showGridStatistics:
nObstacleCells: 498440 nAccelCells: 0 nFluidCells: 801560
minRho: 1.0000 maxRho: 1.0000 mass: 1.300000e+06
minU: 0.000000e+00 maxU: 0.000000e+00
LBM_showGridStatistics:
nObstacleCells: 498440 nAccelCells: 0 nFluidCells: 801560
minRho: 1.0000 maxRho: 1.0431 mass: 1.300963e+06
minU: 0.000000e+00 maxU: 1.272361e-02
==18329==
==18329== HEAP SUMMARY:
==18329== in use at exit: 0 bytes in 0 blocks
==18329== total heap usage: 4 allocs, 4 frees, 428,801,136 bytes allocated
==18329==
==18329== All heap blocks were freed -- no leaks are possible
==18329==
==18329== For counts of detected and suppressed errors, rerun with: -v
==18329== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我把二进制代码上传到here,有兴趣的可以参考。汇编程序实际上是由二进制重写器生成的,而我曾经能够生成无错误的代码。所以我相信这可能不是一个难以调试的指针取消引用问题,应该很容易修复。但是,我真的不知道哪里出了问题,而且在 gdb 调试中它似乎完全正常 (x/10x 0x40337
)
所以这是我的问题,
给定调试信息 (x/10x 0x40337c
),哪里可能出错?
为什么二进制代码不会在valgrind
中崩溃?
Valgrind runs your code on a simulated x86 CPU。显然它不模拟对齐检查。
SSE 指令的 128 位和更大内存操作数始终需要自然对齐。 (例如,对于像这样的 16B 负载,到 16B 边界)。例外是 MOVUPS (_mm_loadu_ps
)(和 MOVUPD / MOVDQU)。
0x40337c 不是 16B 对齐的,只有 4B。 (所以你将它与 XORPD 一起使用是很奇怪的,因为我预计 double
至少需要 8B 对齐)。
AVX指令是相反的:默认不需要对齐,但是VMOVAPS确实需要对齐。
我正在尝试调试一段汇编程序 (x86 64-bit
),根据 gdb
信息,使用以下指令时它崩溃了:
xorpd 0x1770(%rip),%xmm12 # 0x40337c <S_0x403230>
然而,在我看来,内存 0x40337c
是完全正常的:
(gdb) x /10x 0x40337c
0x40337c <S_0x403230>: 0x00000000 0x80000000 0x00000000 0x00000000
0x40338c <S_0x403240>: 0xf149f2ca 0x00000000 0x746e7973 0x203a7861
0x40339c <S_0x403248+8>: 0x206d626c 0x6d69743c
另一个有线的事情是,当我在命令行中以及在 gdb
中 运行 时,这段代码每次都会崩溃。但是,当我在 valgrind
中调试它时,它不会崩溃!
☁ src [master] ⚡ valgrind ./a.out 20 reference.dat 0 1 100_100_130_cf_a.of
==18329== Memcheck, a memory error detector
==18329== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==18329== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==18329== Command: ./a.out 20 reference.dat 0 1 100_100_130_cf_a.of
==18329==
MAIN_printInfo:
grid size : 100 x 100 x 130 = 1.30 * 10^6 Cells
nTimeSteps : 20
result file : reference.dat
action : nothing
simulation type: channel flow
obstacle file : 100_100_130_cf_a.of
LBM_showGridStatistics:
nObstacleCells: 498440 nAccelCells: 0 nFluidCells: 801560
minRho: 1.0000 maxRho: 1.0000 mass: 1.300000e+06
minU: 0.000000e+00 maxU: 0.000000e+00
LBM_showGridStatistics:
nObstacleCells: 498440 nAccelCells: 0 nFluidCells: 801560
minRho: 1.0000 maxRho: 1.0431 mass: 1.300963e+06
minU: 0.000000e+00 maxU: 1.272361e-02
==18329==
==18329== HEAP SUMMARY:
==18329== in use at exit: 0 bytes in 0 blocks
==18329== total heap usage: 4 allocs, 4 frees, 428,801,136 bytes allocated
==18329==
==18329== All heap blocks were freed -- no leaks are possible
==18329==
==18329== For counts of detected and suppressed errors, rerun with: -v
==18329== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我把二进制代码上传到here,有兴趣的可以参考。汇编程序实际上是由二进制重写器生成的,而我曾经能够生成无错误的代码。所以我相信这可能不是一个难以调试的指针取消引用问题,应该很容易修复。但是,我真的不知道哪里出了问题,而且在 gdb 调试中它似乎完全正常 (x/10x 0x40337
)
所以这是我的问题,
给定调试信息 (
x/10x 0x40337c
),哪里可能出错?为什么二进制代码不会在
valgrind
中崩溃?
Valgrind runs your code on a simulated x86 CPU。显然它不模拟对齐检查。
SSE 指令的 128 位和更大内存操作数始终需要自然对齐。 (例如,对于像这样的 16B 负载,到 16B 边界)。例外是 MOVUPS (_mm_loadu_ps
)(和 MOVUPD / MOVDQU)。
0x40337c 不是 16B 对齐的,只有 4B。 (所以你将它与 XORPD 一起使用是很奇怪的,因为我预计 double
至少需要 8B 对齐)。
AVX指令是相反的:默认不需要对齐,但是VMOVAPS确实需要对齐。