顺序代码执行中有趣的行为

用户名

编辑2:我仍然停留在这里,但问题很可能是在自动矢量化重写系统中,这与这个问题无关。我在下面的评论中提到的valgrind的SIGILL输出上再次更新此问题

==10478== Process terminating with default action of signal 4 (SIGILL) 
==10478== Illegal opcode at address 0x423F4C ==10478== at 0x423F4C: sp_private_9_compute (smmintrin.h:209) 
==10478== by 0x4247F4: sp_private_9__timeCompute 

在调试SSE代码时,首先要检查是否看到valgrind引发了SIGILL,是您的VALGRIND是最新的。在我的情况下,我使用的是V3.6,该版本在SSE4内在支持中存在错误。由于不了解_mm_mullo_epi32指令,SIGILL被b / c提出。将其更新到V3.9之后,valgrind可以更好地定位SSE程序的实际问题。

如果我找到更多相关的调试提示,我将再次更新此问题。


编辑1:我希望有人可以确认我对调试跟踪中非顺序行为的观察是准确的。


首先,这是一个有关C调试的非常具体的问题。如果您通读并提供任何反馈意见,我将不胜感激。

背景:我正在使用代码生成系统,最近我不断从glibc获得“双重释放或破坏”。因此,我使用额外的调试信息重新编译了自动生成的代码,并使用gdb运行了它而且或者我现在脑筋急转弯,或者实际上我在顺序代码执行中观察到了非顺序行为

代码

LINE:6851     if(self->_garbage != 0) {
LINE:6852            sp_env_list_free_children(self->_garbage);
LINE:6853            sp_env_list___del__(self->_garbage);
LINE:6854            sp_env_free(self->_garbage, sizeof(sp_env_list_t));
LINE:6855     }//End of if
LINE:6856   }//End of an outer if structure
LINE:6857 }//End of the function call containing the if structure

在调试跟踪之后,我将解释free和del函数。

调试跟踪

6851   if (((self->_garbage != 0))) {
(gdb) step
6852   sp_env_list_free_children(self->_garbage);
(gdb) print self->_garbage 
$1 = (sp_env_list_t *) 0x649080
(gdb) step
6853   sp_env_list___del__(self->_garbage); 
(gdb) print self->_garbage 
$2 = (sp_env_list_t *) 0x649080
(gdb) step
6854      sp_env_free(self->_garbage, sizeof(sp_env_list_t )); 
(gdb) print self->_garbage 
$3 = (sp_env_list_t *) 0x649080
(gdb) step
6857   }
(gdb) print self->_garbage 
$4 = (sp_env_list_t *) 0x649080
(gdb) step
sp_private_11___del__ (self=<value optimized out>) at sp_moddft_int32.c:6854
6854      sp_env_free(self->_garbage, sizeof(sp_env_list_t )); 
(gdb) print self->_garbage 
Cannot access memory at address 0x18
(gdb) step
Single stepping until exit from function sp_env_free, 
which has no line number information.
*__GI___libc_free (mem=0x649080) at malloc.c:3692
3692    malloc.c: No such file or directory.
    in malloc.c

在调试跟踪中可以看到,它在6854行之后到达6857行,然后再次回到6854行。由于self-> _ garbage已被完全释放,因此应该在其中发生“双重释放或损坏”。但是,整个功能是连续的,没有循环。我不明白为什么它会跳回来。

为完整起见,if结构中的三个函数用于:

  • sp_env_list_free_children()将所有e-> _ data从e = self-> _ garbage-> head释放到e = self-> _ garbage-> tail。
  • sp_env_list_ del()从self-> _ garbage-> head删除指向self-> _ garbage-> tail的指针
  • sp_env_free()释放self-> _ garbage指针

如果不清楚,我可以提供任何其他信息。我希望有人至少可以确认我对非顺序行为的观察是准确的。非常感谢!

当您单步执行优化的代码时,它似乎常常随机出现。只要保持定义的顺序关系,优化器就可以自由地重组代码流。

在这种情况下,我怀疑您正在看到尾部调用优化(TCO)的结果。您的最终调用sp_env_free是一个尾部调用,假设它所在的函数已经void返回。因此,该函数可以还原其被调用方保存的寄存器(即,执行结尾),然后跳转到sp_env_free,而不是先调用sp_env_free然后执行结尾。这样可以节省堆栈框架和一些设置堆栈框架的说明。

由于结尾处在函数的末尾,因此名义上它的行号为6857,即使该行上可见的所有内容都是紧括号。因此,TCO与您看到的行号顺序完全一致。我敢肯定这不是唯一的可能性。通常,要想出一个好的优化器并不容易。如果您真的想知道,可以尝试使用查看生成的汇编代码-S,但是鉴于您的文件至少有6857行,也可能不容易解密。

如果要明智地调试程序,请关闭优化。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Java中有趣的线程行为

来自分类Dev

Java中有趣的反射代码

来自分类Dev

在NSTask的源代码中有趣的地方

来自分类Dev

Scala中的有趣线程行为

来自分类Dev

上界Java通配符的有趣行为

来自分类Dev

有趣的往返时间行为

来自分类Dev

有趣的全文搜索行为

来自分类Dev

将变量变成函数?(代码有效,有趣的行为)

来自分类Dev

有条件的MySQL中有趣的查询

来自分类Dev

带有前缀符号的有趣行为

来自分类Dev

xdmp:node-删除有趣的行为

来自分类Dev

IE中的JavaScript搜索功能有趣行为

来自分类Dev

IE中的JavaScript搜索功能有趣行为

来自分类Dev

从DLL实例化类时的有趣行为

来自分类Dev

当Layout Inflater放大EditText时有趣的线程行为

来自分类Dev

xdmp:node-删除有趣的行为

来自分类Dev

在PHP中比较整数和数组的有趣行为

来自分类Dev

有趣的拼图

来自分类Dev

有趣的classCastException

来自分类Dev

Kotlin 中是否有简单的有趣的 addDetail 代码?

来自分类Dev

这段有趣的JavaScript代码如何工作?

来自分类Dev

有趣的GCC链接

来自分类Dev

C有趣的循环

来自分类Dev

有趣的Awk问题

来自分类Dev

使用动态分配的数组的C ++函数中有趣的语法错误

来自分类Dev

Node.js REPL具有自定义eval函数的有趣行为

来自分类Dev

带有自定义eval函数的Node.js REPL有趣行为

来自分类Dev

当没有收到正确数量的参数时,str replace的行为很有趣

来自分类Dev

带有空元素的有趣数组JavaScript行为