c++ - ARM架构中C函数如何返回大小超过一个字的值

标签 c++ c arm

在C程序中,内存布局由.BSS、.DATA、.TEXT、HEAP和STACK组成。当函数返回值小于一个字时,它会转到R0寄存器,但如果返回值大于一个字,它会通过内存返回。例如:

LargeType t;
t = func(arg);

实现为:

LargeType t;
(void) func(&t,arg);

我的问题是编译器使用内存的哪一部分来过去“t”?

最佳答案

ARM C++ ABI本质上使用 Itanium C++ ABI(异常(exception)情况除外)。在该 ABI 中,按值返回大对象的调用约定是调用者传递一个隐藏指针,并且函数使用该指针在 return 语句中创建对象。这就是返回值优化的实现方式。

现在,您提供的翻译不正确。您开始使用的代码使用赋值而不是初始化:

LargeType t;
t = func(arg);

编译器完成的翻译将相当于:

LargeType t;
LargeType __tmp;
func(&__tmp,arg);
t.operator=(__tmp);
__tmp.~LargeType();

临时变量将在堆栈中创建,地址传递给将使用它来创建对象的函数。然后将发生赋值,并且在完整表达式 t = func(arg); 的末尾,临时变量将被销毁。

将其与初始化情况进行比较:

LargeType t = func(arg);

在这种情况下,编译器可以执行您提到的转换,翻译后的代码将是:

LargeType t;
func(&t,arg);

非常重要的区别是初始化和赋值是完全不同的操作。在初始化的情况下,对象变成,什么都没有,现在有一些东西。在赋值的情况下,对象已经曾经,它有一个状态,并且它可能正在管理资源。如果允许您建议的转换,则此代码将泄漏内存:

struct Test {
   int *p;  // assume other members make this object large
   Test() : p(new int()) {}
   Test(int i) : p(new int) { *p = i; }
   Test(Test const & other) : p(new int) { *p = other->p; }
   ~Test() { delete p; }
   Test& operator=(Test const & other) { *p = other->p; }
};
Test f(int arg) {
    return Test(1)
}
Test t;
t = f(5);

转换后的代码会泄漏的地方:

Test t;    // allocates a pointer
f(&t, 5);  // expands to:
           // __ret->p = new int;  // leak!
           // *(__ret->p) = 5;

关于c++ - ARM架构中C函数如何返回大小超过一个字的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20225586/

相关文章:

c - ARM 汇编中的递归打印 100

c++ - 放置 new 以避免复制构造函数

c - scanf 卡住并继续接受输入

在 C 语言中比较和交换机器码

c++ - 使用 Socket 发送 POST 请求,但会占用大量内存

c - 与 0 进行比较与与值进行比较是否更快?

assembly - 磁盘 IO 操作在内核级程序集中通常如何看待?

c++ - 避免在 libgmp 中中止

c++ - mysql C++ 不会用 make 编译,但如果 g++ 参数放在 cmd 行

c++ - Opencv 图像包装器 cpp