使用NSInvocation时,arm64上的EXC_BAD_ACCESS崩溃

阿巴穆特

我已经开始准备一个旧项目来支持arm64架构。但是,当我尝试在64位设备上执行此代码时,我在[invocation keepArguments]上遇到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];
        }
    }
}

看来参数有些问题。

尼基塔·伊万尼舒琴科(Nikita Ivaniushchenko)

这就是具有相同目的的东西。

+ (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(在arm和arm64上均为32位),这导致从开始读取64位32位变量的地址-以及数据中的垃圾)。无论如何,您的实现有潜在的危险-您将传递给包装方法的所有参数都视为与调用方法中的参数具有相同类型。

这是修改后的代码,可以正常工作:

- (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];
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

NSInvocation返回值,但使用EXC_BAD_ACCESS会使应用程序崩溃

来自分类Dev

使用NativeCSS时EXC_BAD_ACCESS

来自分类Dev

解雇UIViewController时EXC_BAD_ACCESS崩溃

来自分类Dev

NSOutlineView EXC_BAD_ACCESS在展开时崩溃

来自分类Dev

NSInvocation获取导致EXC_BAD_ACCESS的目标

来自分类Dev

CGContextDrawPDFPage在OS X 10.8上使用EXC_BAD_ACCESS随机崩溃

来自分类Dev

应用程序在CGContext.drawPDFPage上使用EXC_BAD_ACCESS崩溃

来自分类Dev

UITextFieldDelegate崩溃(exc_bad_access)

来自分类Dev

NewRelic因EXC_BAD_ACCESS而崩溃

来自分类Dev

使用object_setIvar时为EXC_BAD_ACCESS

来自分类Dev

使用cfnetwork写入输出流时,exc_bad_access

来自分类Dev

使用泛型时为EXC_BAD_ACCESS

来自分类Dev

使用scrollViewDidScroll时出错EXC_BAD_ACCESS

来自分类Dev

在代码中添加UINavigationController时使用EXC_BAD_ACCESS

来自分类Dev

使用数组C ++时的“ EXC_BAD_ACCESS”

来自分类Dev

CCHmac上的EXC_BAD_ACCESS

来自分类Dev

[UICollectionView setCollectionViewLayout:]上的EXC_BAD_ACCESS

来自分类Dev

在performSelectorInBackground上为EXC_BAD_ACCESS

来自分类Dev

仅在iPad上的EXC_BAD_ACCESS

来自分类Dev

setMask上的EXC_BAD_ACCESS

来自分类Dev

生成nspredicate时EXC_BAD_ACCESS

来自分类Dev

执行块时EXC_BAD_ACCESS

来自分类Dev

EXC_BAD_ACCESS 执行关闭时

来自分类Dev

在iOS7上运行的相机无法打开,然后崩溃(EXC_BAD_ACCESS)

来自分类Dev

SKShapeNode有时会在dealloc EXC_BAD_ACCESS上产生崩溃

来自分类Dev

尝试获取设备位置时,iOS应用程序崩溃-线程1:EXC_BAD_ACCESS

来自分类Dev

尝试获取设备位置时,iOS应用程序崩溃-线程1:EXC_BAD_ACCESS

来自分类Dev

使用协议组成的EXC_BAD_ACCESS

来自分类Dev

使用MPMoviePlayerViewController的EXC_BAD_ACCESS

Related 相关文章

热门标签

归档