I have an application built with gcc v7.3.0 and executing on an Intel(R) Xeon(R) CPU E3-1220 v6
chip that corrupts stack memory deterministically and gets a SEGV due to executing a mov
instruction. I ran valgrind
and no memory corruption was reported.
I have a struct SolutionPattern
on the stack and its member variable, of type const float * const &
, is getting clobbered when I begin calling the member function, inline void RoleToEquation(float threshold)
. In GDB
, when enetring the member function, the forth instruction, mov %rdi,-0x18(%rbp)
, causes the corruption as shown in the debugger:
Dump of assembler code for function SolutionPattern::RoleToEquation(float):
0x00007fff9556b684 <+0>: push %rbp
0x00007fff9556b685 <+1>: mov %rsp,%rbp
0x00007fff9556b688 <+4>: sub $0x20,%rsp
=> 0x00007fff9556b68c <+8>: mov %rdi,-0x18(%rbp)
0x00007fff9556b690 <+12>: movss %xmm0,-0x1c(%rbp)
0x00007fff9556b695 <+17>: mov -0x18(%rbp),%rax
0x00007fff9556b699 <+21>: pxor %xmm0,%xmm0
0x00007fff9556b69d <+25>: movss %xmm0,0x88(%rax)
0x00007fff9556b6a5 <+33>: mov -0x18(%rbp),%rax
[...]
End of assembler dump.
(gdb) si
Hardware watchpoint 99: *$285
Old value = (const float * const) 0x7fffafb6087a <fflush+106>
New value = (const float * const) 0x7fffffff9ac0
0x00007fff9556b690 in SolutionPattern::RoleToEquation (this=0x7fffffff9ac0, threshold=4.59163468e-41) at calculate_edge.h:250
(gdb) disas
Dump of assembler code for function SolutionPattern::RoleToEquation(float):
0x00007fff9556b684 <+0>: push %rbp
0x00007fff9556b685 <+1>: mov %rsp,%rbp
0x00007fff9556b688 <+4>: sub $0x20,%rsp
0x00007fff9556b68c <+8>: mov %rdi,-0x18(%rbp)
=> 0x00007fff9556b690 <+12>: movss %xmm0,-0x1c(%rbp)
0x00007fff9556b695 <+17>: mov -0x18(%rbp),%rax
0x00007fff9556b699 <+21>: pxor %xmm0,%xmm0
0x00007fff9556b69d <+25>: movss %xmm0,0x88(%rax)
0x00007fff9556b6a5 <+33>: mov -0x18(%rbp),%rax
[...]
End of assembler dump.
The member function source code begins like this:
inline void RoleToEquation(float threshold) {
A = B = 0.f;
C = threshold;
D = E = 0.f;
F = threshold;
[...]
}
A
, B
, C
, D
, E
, and F
are float
member variables of the struct that occur several member variables after the memory that is being corrupted.
I don't fully understand the disassembly, but it appears that the function setup is still being run and the setting of A
and B
to 0.f
has not started yet. I notice in the debugger that the argument threshold
is uninitialized until the fifth instruction, movss
, executes. How does the code to set up the argument variable threshold
on the stack cause the struct to be corrupted that is located in the calling frame's stack memory?
What is likely going on here and how can I go about figuring out the source of this corruption. Does the disassembly look proper? Does this look like a compiler bug? Note, only the debug build crashes, optimized build does not crash. What is being performed by the first four instructions of this member function? Is it improperly setting up the frame for the new function being called?