背景:我们在函数foo(int *p)
中看到非常间歇性的崩溃。在解除引用p
时发生崩溃,在这些情况下,其值为0xffffffff
。对核心转储的分析表明,从以下程序集片段中调用foo()
:
bne ... somewhere else
lw $a0,44(sp)
lw $a0,40(sp)
jal foo()
lui s1, 0x1000
检查核心转储中的内存显示44(sp)
为0xffffffff
,而40(sp)
是我们打算取消引用的正确值。但是,a0
内部foo()
的值0xffffffff
为foo()
。 (重要的是要注意,在这种情况下foo()
只是访问一个成员;所以它实际上是a0
中已经尝试通过ra
访问并崩溃的第一条指令。此外, s1
指向上述代码段后面的说明,而0x10000000
目前包含foo()
,因此我们非常确信lw
确实来自上述代码段。)
目前我们唯一的理论是连续两个a0
到jal foo()
是一个危险 - 要么是一个记录的,在这种情况下,这看起来像编译器错误;或者没有证件的。
那么:以上大会合法吗?如果是的话,还有其他关于可能发生什么的想法吗?
谢谢!
更新:好吧,事实证明这是一场疯狂的追逐:一位同事对coredump的重复分析在我错过的代码中找到了一条路径,那里有一个跳跃在将a0
设置为44(sp)
后立即直接指向{{1}}指令。换句话说,代码中有一条路径与我们看到的不涉及危险的结果一致,或“跳过指令”或任何东西......我以为我检查了这个,但我想我要么没有' t,或者错过了...... :(
无论如何,我接受了markgz的回答,因为它回答了我关于这些指令合法性的原始问题(显然它们是)。
答案 0 :(得分:1)
快速搜索MIPS32R2 ISA的MIPS文档并未在LW
指令后对LW
显示任何限制。
可能是您CPU中MIPS实现的错误。需要注意的事项包括:
NOP
,SSNOP
或SYNC
指令会导致问题消失吗?