У меня есть приложение, созданное с помощью gcc v7.3.0 и выполняющееся на микросхеме Intel(R) Xeon(R) CPU E3-1220 v6
, которое детерминирует повреждение стековой памяти и получает SEGV из-за выполнения инструкции mov
. Я запустил valgrind
, и о повреждениях памяти не сообщалось.
У меня в стеке struct SolutionPattern
, а его переменная-член типа const float * const &
забивается, когда я начинаю вызывать функцию-член inline void RoleToEquation(float threshold)
. В GDB
при вводе функции-члена четвертая инструкция mov %rdi,-0x18(%rbp)
вызывает повреждение, как показано в отладчике:
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.
Исходный код функции-члена начинается так:
inline void RoleToEquation(float threshold) {
A = B = 0.f;
C = threshold;
D = E = 0.f;
F = threshold;
[...]
}
A
, B
, C
, D
, E
и F
являются float
переменными-членами структуры, которые появляются через несколько переменных-членов после повреждения памяти.
Я не до конца разбираюсь в разборке, но похоже, что настройка функции все еще выполняется, а настройка от A
и B
до 0.f
еще не началась. Я замечаю в отладчике, что аргумент threshold
не инициализируется до тех пор, пока не будет выполнена пятая инструкция movss
. Как код, устанавливающий переменную аргумента threshold
в стеке, приводит к повреждению структуры, расположенной в памяти стека вызывающего фрейма?
Что, вероятно, происходит здесь и как я могу выяснить источник этой коррупции. Разборка выглядит правильно? Это похоже на ошибку компилятора? Обратите внимание, что происходит сбой только отладочной сборки, оптимизированная сборка не дает сбоя. Что выполняют первые четыре инструкции этой функции-члена? Неправильно ли настроена рамка для вызываемой новой функции?