C语言 函数调用约定 Powerpc vs Intel



我需要以下信息:

Powerpc 和英特尔处理器在调用函数时如何分配堆栈?- 在每种情况下,堆栈大小的依据是什么确定,即 powerpc 和英特尔 x86 处理器- 参数和返回地址存储在堆栈上的什么位置。

基本上,我需要在每种情况下堆叠布局。

我遇到的情况是我的程序在英特尔机器中崩溃(分段错误(并且在 powerpc 上运行良好。我已经找到了崩溃的原因,代码片段如下:

int function_a(int a)
{
   int local_var = 1;
   int ret_var;
   ret_var = function_b(&local_var);
}
int function_b (int* local_var_in_calld_fn)
{
   while (some_condition)
   {
      *local_var_in_calld_fn = some_computed_value; /* Cause of crash */
      local_var_in_calld_fn++; 
   }
   return something;
}

一些值在"可能"在堆栈上并因此崩溃的地址上更新。代码完全不会在位置崩溃,但是在 gdb 中调试时,在 x86 机器上从此函数出来后,在外面的某个地方崩溃。

我怀疑它破坏了堆栈,但它并没有在 powerpc 上崩溃。

谢谢

这里有一个明显的堆栈溢出。
function_a 获取指向单个int的指针,递增(因此它指向堆栈中的其他位置(并写入。

堆栈溢出的结果非常不可预测。它取决于调用约定,但也取决于编译器决策,例如变量的排序和内联,这些决策没有以任何方式标准化。

我不会纠结于弄清楚为什么它在一种情况下崩溃而不是在另一种情况下崩溃。
最好只是修复它。

操作系统负责分配堆栈,而不是处理器。PowerPC 处理器甚至不知道或不关心堆栈;按照惯例,"堆栈指针"r1,是一个完全正常的寄存器,但这依赖于平台。您尚未说明这在哪个平台上运行。

在这种情况下,崩溃是由行local_var_in_calld_fn++;引起的,这是未定义的行为(也许你的意思是*local_var_in_calld_fn++;(。那么问题就是"为什么未定义的行为不会崩溃?"答案很简单:

定义的行为是未定义的,因此绝对可能发生任何事情,包括不崩溃。

除此之外,为什么它不会崩溃的最简单解释是因为some_condition在 PPC 上评估为 false(因为它是单核的,所以锁争用较少,所以你还没有注意到崩溃(。

我还可以想出一个不会崩溃的情况:

  • 在这个特定的平台上,堆栈会长大(我不确定是否有任何常见的堆栈这样做(。这意味着写入*local_var_in_calld_fn有效地增加了堆栈,并且可能会破坏function_b()堆栈,但不会破坏任何调用方的堆栈。
  • function_b()是一个"叶函数"(即不进行任何函数调用(,因此不需要将 LR 保存在堆栈上。这意味着写入*local_var_in_calld_fn不会破坏返回地址。
  • some_condition很快就会变成假,以至于您不会用完堆栈。

最新更新