1

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 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

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank Bavarious for explanation and solution, it's work perfectly. I was thinking that variables defined in function scope AND referenced in global variable was automatically keep in memory. And now I'll use self = [super init]; if (!self)return nil;

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.