【问题标题】:C address of function parameter?函数参数的C地址?
【发布时间】:2016-04-03 19:48:50
【问题描述】:

在符合 C89/C99 的编译器上使用函数参数的地址是否保证安全/可移植?

例如,如果函数参数满足特定的大小和对齐要求,则 32 位 ARM 的 AAPCS 使用寄存器 r0-r3 进行参数传递。我会假设使用通过寄存器传递的参数的地址会产生意想不到的结果,但我在我正在使用的 ARM 编译器上运行了一个测试,如果代码尝试引用地址,它似乎会将这些参数重新定位到堆栈这些参数。虽然它在我的特定应用程序中看起来很安全,但我想知道这是否可以在可以直接利用寄存器传递函数参数的架构(使用符合 ANSI/ISO 的编译器)中得到保证。

标准是否定义了这种行为?

【问题讨论】:

  • 这在 ISO C 标准下是允许的
  • 什么MM说。我更好奇可能在单独的源文件中并单独编译的调用代码如何知道何时通过寄存器传递与通过堆栈传递。或者当函数签名满足大小/对齐要求(并且调用的代码负责移动到堆栈)时,ARM是否总是假设通过寄存器传递?
  • 参数根据 ABI 通过合适的寄存器传递。然后将地址在函数体中的参数迁移到自动存储(也称为在堆栈上)。
  • 函数参数是函数内部的普通变量。除非您使用 register 存储说明符,否则标准保证您可以获取他们的地址。
  • @selbie:这不会改变接口,正如 ABI 定义的那样(对于现代 ARM,AAPCS)。内部隐藏在函数内部。

标签: c arm


【解决方案1】:

在 C 中,唯一不能获取地址的左值是位域(不能出现在函数参数中)和 register 存储类的变量或函数参数。获取参数的地址是完全安全的,但请记住,参数是按值传递的,因此您必须确保在其生命周期结束后不要使用局部变量或参数的地址。

通常,编译器会检查哪些局部变量和参数是一元 & 运算符的操作数。然后在适当的时候将它们复制到合适的 RAM 中。调用约定对此没有影响。

【讨论】:

  • 第二段在技术上对于许多实现来说是正确的,在这里添加是个好主意。但是,应该强调的是,C 标准并未涵盖参数传递和详细说明如何获取地址的内容。有些架构允许通过正常的内存读取访问 CPU 寄存器,或者甚至不使用寄存器来传递参数(有些甚至没有可用的寄存器)等。
  • @Olaf 我不知道你为什么需要强调这一点。 “一般……”的措辞不是清楚地表明存在机制不同的平台吗?即使在将寄存器映射到内存中的平台上,至少如果将地址传递给另一个函数,它也不能指向寄存器,因为被调用者可能会决定将这个寄存器用于自己的目的。
  • 我试图强调 C 标准并不强制它。 “一般”是有问题的,因为这是平台的问题,并且有些平台的行为方式并非如此。我不会打赌哪个有更多的实现,同时牢记 CPU 架构的多样性(不要了解嵌入式世界,它刚刚开始被 Cortex-M 简化——不管是好是坏)。如果这样的别名地址被传递是不同的主题,需要采取其他措施。
猜你喜欢
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 2015-04-18
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多