Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法将objc_msgsend安全地强制转换为可变长度参数函数_C_Objective C_Objective C Runtime - Fatal编程技术网

无法将objc_msgsend安全地强制转换为可变长度参数函数

无法将objc_msgsend安全地强制转换为可变长度参数函数,c,objective-c,objective-c-runtime,C,Objective C,Objective C Runtime,假设我在运行时得到一个对象和它的一个选择器,我打算安全地调用它,所以我定义了 #define objc_msgsend_va ((void (*)(id, SEL, ...))objc_msgsend) #define Call_object(obj, sel, ...) objc_msgsend_va(obj, sel, ## __VA_ARGS__) 我是否可以用call_object宏安全地替换任何方法调用,否则可能导致某种崩溃 这是为了定义一个宏来在iOS设备上运行任意运行时方法,我

假设我在运行时得到一个对象和它的一个选择器,我打算安全地调用它,所以我定义了

#define objc_msgsend_va ((void (*)(id, SEL, ...))objc_msgsend)

#define Call_object(obj, sel, ...) objc_msgsend_va(obj, sel, ## __VA_ARGS__)
我是否可以用call_object宏安全地替换任何方法调用,否则可能导致某种崩溃

这是为了定义一个宏来在iOS设备上运行任意运行时方法,我无法显式强制转换来更正每个方法的函数类型,所以我使用了可变长度参数

主要考虑的是这样使用宏的安全性。

底线: 不,这绝对不安全。它在许多常见情况下都能工作,但va_args与直接向函数传递参数不同

请,请,请,使用
NSInvocation
它可以为您解决99%的问题,同时更安全。它可能无法解决某些边缘情况(例如,参数列表中的SSE/AVX向量),但它将比您可能一起解决的问题有很大的进步

让我们按体系结构对此进行分解,看看这可能在哪里起作用

普遍的 这些问题将无处不在,没有真正的解决办法

  • 当作为va_args传递时,浮点总是升迁为双倍。见第§6.5.2.2节

  • 这同样适用于
    short
    s和
    char
    s。它们也都会被放大,在经过时会造成很多痛苦和痛苦。从技术上讲(与浮点数不同,浮点数有时在特殊的FPU寄存器中传递),对于整数类型,可以通过将它们包装在单个元素结构中来解决这一问题。这将阻止他们晋升。不过,请不要这样做

  • 联合,或复杂结构。需要额外的对齐、填充和注意事项。如果你想要一个稳定的解决方案,你必须深入研究编译器代码

  • 如果您开始接触返回值,事情就更复杂了,您需要了解结构何时被架构打包到返回值的寄存器中(参见前面的讨论)

  • PowerPC 我不在乎这个。如果您仍然需要针对这些macOS设备,有两件事:

  • 我为你感到很难过

  • 在这个问题上,你可能比我有更多的背景知识。祝你好运,祝你好运

  • x86 32位x86相当正常。我脑子里没有复杂的寄存器参数,我觉得这可能是相当理智的。除了前面提到的问题之外,最大的问题是x87 FPU引起的问题。避免漂浮物,你可能不会在这里烧掉世界

    x86-64 64位x86是另一个怪兽。您必须了解编译器如何将寄存器分配给参数(和返回值!),当然,还要了解新的SSE寄存器如何分配给浮点

    ARMv6/ARMv7/ARMv7s(32位ARM) 我将把这些放在一起,从这个角度看没有什么大的区别

    与x86-64一样,如果希望100%安全,您必须了解一些寄存器在堆栈中的位置,但是如果内存调用,这里的浮点传递更简单

    苹果在这里会是你的朋友

    ARM64 这是我的知识最不可靠的地方,如果任何信息不正确,我道歉


    大多数函数调用都是完全通过寄存器执行的,所以我们之前所有的担心都还在这里。现在有新的浮点FPU寄存器需要处理,但如果你已经做到这一点,没有什么是无法克服的。

    感谢你的回答,NSInvocation与va_列表集成,在定义的C_类型的帮助下,确实解决了我的大部分问题,最后一个可能是,我不能用va_args将任意大小的类型出列,GNU澄清它的实现可能会随着时间的推移而改变。对于这些类型的函数,我只返回nil,现在它的工作方式类似于带有KVC包装特性的objc_msgSend。