开发者

Problem in Obj-c to access to previously defined C Struct data

开发者 https://www.devze.com 2023-02-25 16:30 出处:网络
I\'m new on objc/Cocoa and I never use C before. I\'ve a problem to get previously defined C struct data…

I'm new on objc/Cocoa and I never use C before.

I've a problem to get previously defined C struct data…

Here's my code :

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

When I click on a button in my开发者_Go百科 app that call toggleAuthentification:, I get error code -60008 (errAuthorizationInternal).

In the debugger I can see authRights.count = 1, that correct, but authRights.items do not correspond in any way to data defined in init.

I try many different way but I don't find solution.

Please, anyone can explain why it doesn't work like I would it work and how to resolve my problem.

Bil


The problem in your code is memory management.

When you create rightItems[], an array of AuthorizationItem elements, it is created in the stack since rightItems[] is an automatic (local) variable. This means that the memory used by the array is deallocated at the end of the method. Since you’re assigning rightItems[] to authRights.items, authRights.items points to a bogus memory address after -init has finished executing. Any further reference to authRights.items has undefined behaviour and is likely to produce an error in your program.

What you need to do is to create the array in the heap so that it isn’t deallocated when -init has finished executing. You can do that via malloc(). For instance:

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

authRights.items = rightItems;

In theory, you’re responsible for releasing authRights.items when it’s not needed any longer since you’ve allocated memory for it in the heap. Hence, in your -dealloc method:

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

I’ve said in theory because you’re storing the authorisation rights in your application controller. Since the application controller lives throughout the application lifecycle, technically it won’t receive -release or -dealloc. However, it’s good practice and potentially useful in case you rearchitect your application and that code ends up being in a class whose objects are not necessarily alive until the application exits.

One further note: you should assign the return value of [super init] to self in your -init method. This is also good practice since it is possible that [super init] returns a different object than current self.

0

精彩评论

暂无评论...
验证码 换一张
取 消