gpt4 book ai didi

ios - 使用 NSInvocation 时 ARM64 上的 EXC_BAD_ACCESS 崩溃

转载 作者:可可西里 更新时间:2023-11-01 06:20:40 27 4
gpt4 key购买 nike

我已经开始准备一个支持 arm64 架构的旧项目。但是当我尝试在 64 位设备上执行此代码时,我在 [invocation retainArguments] 上遇到 EXC_BAD_ACCESS 崩溃;行

- (void)makeObjectsPerformSelector: (SEL)selector withArguments: (void*)arg1, ...
{

va_list argList;

NSArray* currObjects = [NSArray arrayWithArray: self];
for (id object in currObjects)
{
if ([object respondsToSelector: selector])
{
NSMethodSignature* signature = [[object class] instanceMethodSignatureForSelector: selector];

NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];
invocation.selector = selector;
invocation.target = object;

if (arg1 != nil)
{
va_start(argList, arg1);

char* arg = arg1;

for (int i = 2; i < signature.numberOfArguments; i++)
{
const char* type = [signature getArgumentTypeAtIndex: i];
NSUInteger size, align;
NSGetSizeAndAlignment(type, &size, &align);
NSUInteger mod = (NSUInteger) arg % align;

if (mod != 0)
arg += (align - mod);

[invocation setArgument: arg
atIndex: i];

arg = (i == 2) ? (char*) argList : (arg + size);
}

va_end(argList);
}

[invocation retainArguments];
[invocation invoke];
}
}
}

看来参数有问题。

最佳答案

这是出于同样的目的。

+ (void)callSelectorWithVarArgs:(SEL)selector onTarget:(id)target onThread:(id)thread wait:(BOOL)wait, ...
{
NSMethodSignature *aSignature = [[target class] instanceMethodSignatureForSelector:selector];

if (aSignature)
{
NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
void * arg;
int index = 2;

[anInvocation setSelector:selector];
[anInvocation setTarget:target];

va_list args;
va_start(args, wait);

do
{
arg = va_arg(args, void *);
if (arg)
{
[anInvocation setArgument:arg atIndex:index++];
}
}
while (arg);

va_end(args);

[anInvocation retainArguments];

if (thread == nil)
{
[anInvocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];
}
else
{
[anInvocation performSelector:@selector(invoke) onThread:thread withObject:nil waitUntilDone:wait];
}
}
}

请注意,在需要执行类型转换时,此代码可能不安全。当调用的方法有更长的参数传递给我的 callSelectorWithVarArgs:onTarget:onThread:wait:(例如,调用的方法接收 NSUInteger(在 arm64 上是 64 位)但我传递了 int(在 arm64 上是 32 位) arm 和 arm64)),这会导致从 32 位变量的起始地址读取 64 位 - 以及数据中的垃圾)。无论如何,您的实现具有潜在危险 - 您将传递给包装方法的所有参数视为与调用方法中的参数具有相同类型。

这是您修改后的有效代码:

- (void)makeObjectsPerformSelector:(SEL)selector withArguments: (void*)arg1, ...
{
NSArray* currObjects = [NSArray arrayWithArray: self];
for (id object in currObjects)
{
if ([object respondsToSelector: selector])
{
NSMethodSignature* signature = [[object class] instanceMethodSignatureForSelector: selector];

NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];
invocation.selector = selector;
invocation.target = object;

[invocation setArgument:&arg1 atIndex:2];

NSInteger index = 3;
void * arg;

va_list args;
va_start(args, arg1);

do
{
arg = va_arg(args, void *);
if (arg)
{
[invocation setArgument:&arg atIndex:index++];
}
}
while (arg);

va_end(args);

[invocation retainArguments];
[invocation invoke];
}
}
}

关于ios - 使用 NSInvocation 时 ARM64 上的 EXC_BAD_ACCESS 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27707946/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com