【问题标题】:Problem in Obj-c to access to previously defined C Struct dataObj-c 中访问先前定义的 C 结构数据的问题
【发布时间】:2011-04-13 00:10:34
【问题描述】:

我是 objc/Cocoa 的新手,以前从未使用过 C。

我在获取之前定义的 C 结构数据时遇到了问题……
这是我的代码:

AppController.h

#import <Cocoa/Cocoa.h>

@interface AppController : NSObject {
    AuthorizationRef authRef;
    AuthorizationRights authRights;
    AuthorizationFlags authFlags;
}
- (IBAction)toggleAuthentification:(id)sender;
@end

AppController.m

#import "AppController.h"

@implementation AppController
    - (id)init {
        if (![super init])
            return nil;

        AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef);
        AuthorizationItem rightItems[1] = {{"com.myname.myapp.adminRights", 0, NULL, 0}};
        authRights.count = 1;
        authRights.items = rightItems;
        authFlags = kAuthorizationFlagDefaults | kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize;

        return self;
    }

    - (IBAction)toggleAuthentification:(id)sender {
        NSLog(@"%d", AuthorizationCopyRights(authRef, &authRights, kAuthorizationEmptyEnvironment, authFlags ^ kAuthorizationFlagInteractionAllowed, NULL));
    }
@end

当我单击应用程序中调用 toggleAuthentification: 的按钮时,我收到错误代码 -60008 (errAuthorizationInternal)。
在调试器中我可以看到authRights.count = 1,这是正确的,但authRights.itemsinit 中定义的数据没有任何对应关系。

我尝试了很多不同的方法,但我没有找到解决方案。

请,任何人都可以解释为什么它不能像我希望的那样工作以及如何解决我的问题。

比尔

【问题讨论】:

    标签: objective-c c struct memory-management


    【解决方案1】:

    代码中的问题是内存管理。

    当您创建 rightItems[]AuthorizationItem 元素的数组)时,它会在堆栈中创建,因为 rightItems[] 是一个自动(本地)变量。这意味着数组使用的内存在方法结束时被释放。由于您将rightItems[] 分配给authRights.items,因此authRights.items-init 完成执行后指向一个虚假的内存地址。对authRights.items 的任何进一步引用都有未定义的行为,并且可能会在您的程序中产生错误。

    您需要做的是在堆中创建数组,以便在 -init 执行完成时不会释放它。您可以通过malloc() 做到这一点。例如:

    const size_t numberOfRightItems = 1;
    AuthorizationItem *rightItems = malloc(sizeof(AuthorizationItem)
        * numberOfRightItems);
    rightItems[0] = (AuthorizationItem){"com.myname.myapp.adminRights", 0, NULL, 0};
    
    authRights.items = rightItems;
    

    理论上,您有责任在不再需要时释放 authRights.items,因为您已在堆中为其分配了内存。因此,在您的 -dealloc 方法中:

    - (void)dealloc {
        free(authRights.items);
        super[dealloc];
    }
    

    我说理论上是因为您将授权权限存储在应用程序控制器中。由于应用程序控制器存在于整个应用程序生命周期中,因此从技术上讲,它不会收到-release-dealloc。但是,如果您重新构建应用程序并且代码最终位于其对象在应用程序退出之前不一定处于活动状态的类中,这是一种很好的做法并且可能很有用。

    进一步注意:您应该在您的-init 方法中将[super init] 的返回值分配给self。这也是一种很好的做法,因为[super init] 返回的对象可能与当前的self 不同。

    【讨论】:

    • 感谢 Bavarious 的解释和解决方案,它工作得很好。我在想在函数范围中定义并在全局变量中引用的变量会自动保存在内存中。现在我将使用self = [super init]; if (!self)return nil;
    猜你喜欢
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多