Assigning instance variance in method leads to segfault - objective-c

Below is rather basic objective-c code. It contains one instance variable i. The problem is whenever I attempt to assign to it, it leads to segfault almost immediately following that assignment operation. Note: It does not segfault at the point of assignment. Usually it segfaults after the assignment and I try to invoke a method. ALSO, notice that this is not your standard mac/apple objective-c code. I'm using cygwin (Linux) plain vanilla version of objective-c. So I have to generate my own alloc and dealloc methods.
#import <objc/runtime.h>
#import <objc/Object.h>
#interface Test
{
int i;
}
+(id)alloc;
- (id) init;
- (int) load;
#end
#implementation Test
+(id)alloc
{
self = class_createInstance(self,0);
return self;
}
-(id)init
{
i = 0; // <------ if I comment out this line, there is no segfault
return self;
}
-(int) load
{
return i;
}
#end
int main(int argc, const char * argv[])
{
Test * test = [[Test alloc] init];
int v = [test load]; //segfaults here (NOTE: if I comment out this line, it does not segfault)
return 0;
}
What is causing the segfault?

I expect that, for a root class like yours, you need to explicitly declare the isa instance variable. Without it, your i is being interpreted as though it were the isa, which is why you get a crash.
So:
#interface Test
{
Class isa;
int i;
}
If you didn't intend to create a root class, you should probably inherit from Object or the like.

Related

Why does the static analyzer warn of a garbage value in this code?

With Apple LLVM 4.2 (XCode 4.6), the static analyzer warns "The left operand of '>' is a garbage value" in this class's 'update' method:
Test.h
#import <Foundation/Foundation.h>
typedef struct {
float x;
} TestInnerStruct;
typedef struct {
TestInnerStruct innerStruct;
int value;
} TestOuterStruct;
#interface Test : NSObject {
TestOuterStruct outerStruct;
}
#end
Test.m
#import "Test.h"
#implementation Test
- (id) init {
if (self = [super init]) {
outerStruct.value = 1;
}
return self;
}
- (void) update {
outerStruct.innerStruct = (TestInnerStruct){0.0f};
if (outerStruct.value > 0) {
NSLog(#"Value greater than zero");
}
}
#end
This is a contrived class, made by cutting down the real class to the minimum needed to reproduce this static analyzer warning. In the real class, there are good reasons for using the nested structs.
What path through the code would cause that operand to be a garbage value? Or is the static analyzer getting confused?
Edit for clarification: It's not just that the analyzer's considering the case where [super init] returns nil. I know that because the warning goes away on commenting out the first line of the update method.
Eric is right, and it is apparently a compiler issue: If one changes the definition of TestOuterStruct to
typedef struct {
int value;
TestInnerStruct innerStruct;
} TestOuterStruct;
i.e., if the two elements are interchanged, the code compiles without error.
The outerStruct.value is only set to 1, if self = [super init] succeeds. If is does not (which is of course a VERY rare event, but possible, otherwise the if would not be necessary), the value is not set but garbage.

Is it possible to invoke a msg from a different class?

I have been knocking my head against the wall trying to figure whether it is possible to call a function defined in a different class. Unfortunately, my limited knowledge in Objective C prevented me to reach a satisfactory answer. Basically, I have one class called Caller and a different class called Functions that I would like to hook to at run time. Class Functions will have all the functions defined that caller is going to reference to at run time.
This is the code in its entirety:
--- Caller.h -------------------
#import "Functions.h"
#interface Caller
{
int callerId;
NSMethodSignature *sig;
NSInvocation *func;
}
#property(retain) NSInvocation* func;
#end
--- Caller.m -------------------
#import "Caller.h"
#implementation Caller
#Synthesize func;
-(id)initWithFunction: (SEL)f
{
if (self)
{ Sig = [Caller instanceMethodSignatureForSelector: f];
func= [NSInvocation invocationWithMethodSignature: Sig];}
return self;
}
#end
--- Functions.h -------------------
#interface Functions
-(int)SayHello;
#end
--- Functions.m -------------------
#import "Functions.h"
#implementation
-(int)SayHello
{
NSLog(#"Hello");
return 0;
}
---------main.m-----------------
#import <Foundation/Foundation.h>
#import "Caller.h"
#import "Functions.h"
int main
{
NSAutoreleasePool * pool [[NSAutoreleasePool alloc]init];
Functions* ftn = [[Functions alloc]init];
Caller * c = [[Caller alloc]initWithFunction: #selection(SayHello)];
[c.func setTarget:c];
[c.func invoke];
[pool drain];
return 0;
}
The code was compiling fine but at run time, it encountered an error because instanceMethodSignatureForSelector is 0. If I make Caller class inherit from Functions class, then the program will work like a charm. But Functions class in my case has to be independent from Caller class. Is there a work around?
+instanceMethodSignatureForSelector: returns nil because Caller doesn't have such a method - it is implemented in another class which you can't know with the given data at that point.
Instead you can retrieve the method signature from the target later, e.g.:
#implementation Caller
// ...
- (void)invokeWithTarget:(id)target {
NSMethodSignature *sig = [target methodSignatureForSelector:sel_];
// ...
}

Is it possible to declare an Objective-C method outside a class?

I know that you can declare a C function outside of a class, but is it possible to declare a Objective-C method outside of a class?
Example:
// Works
void printHelloC()
{
NSLog(#"Hello.");
}
// Error
-(void) printHelloOC
{
NSLog(#"Hello.");
}
int main (int argc, const char * argv[])
{
#autoreleasepool {
printHelloC();
[self printHelloOC];// 'self' obviously would not work but you get the idea
}
return 0;
}
It depends. You can do something similar with method adding at runtime:
#import <objc/runtime.h>
void myCustomMethod(id self, SEL _cmd, id arg1, id arg2)
{
NSLog(#"This is a test, arg1: %#, arg2: %#", arg1, arg2);
}
int main(int argc, char *argv[])
{
Class NSObjClass = [NSObject class];
class_addMethod(NSObjClass, #selector(myNewMethod::), (IMP) myCustomMethod, "v#:##");
NSObject myObject = [NSObject new];
[myObject myNewMethod:#"Hi" :#"There"];
[myObject release];
return 0;
}
But that is about it outside of a #class construct, and it really just covers up what happens with a category.
You can use a category for this.
As an instance method:
#interface NSObject (MONStuff)
- (void)printHelloOC;
#end
#implementation NSObject (MONStuff)
- (void)printHelloOC
{
NSLog(#"Hello.");
}
#end
// in use:
NSObject * obj = ...;
[obj printHelloOC];
As a Class method:
#interface NSObject (MONStuff)
+ (void)printHelloOC;
#end
#implementation NSObject (MONStuff)
+ (void)printHelloOC
{
NSLog(#"Hello.");
}
#end
// in use:
[NSObject printHelloOC];
Of course, you must associate that with a class - so it's not exactly the same as you posted, but it's a close definition + declaration separate from the formal class declaration.
A method without an associated class is a meaningless concept. Functions, as you've noted, are just fine.
No, it is not possible - you will need to either use global C functions or class (+) methods.
Objective c functions are always associated with a class. If you mean you want to use an objective-c function without instantiating a class, you can of course write a class method (notice the plus sign instead of the usual hyphen)
#interface Test
+ (void)aClassMethod;
#end
then you can call it by calling
[Test aClassMethod];

How to call an Objective-C Method from a C Method?

I have an Obj-C object with a bunch of methods inside of it. Sometimes a method needs to call another method inside the same object. I can't seem to figure out how to get a C method to call a Obj-C method...
WORKS: Obj-C method calling an Obj-C method:
[self objCMethod];
WORKS: Obj-C method calling a C method:
cMethod();
DOESN'T WORK: C method calling an Obj-C method:
[self objCMethod]; // <--- this does not work
The last example causes the compiler spits out this error:
error: 'self' undeclared (first use in this function)
Two questions. Why can't the C function see the "self" variable even though it's inside of the "self" object, and how do I call it without causing the error? Much thanks for any help! :)
In order for that to work, you should define the C method like this:
void cMethod(id param);
and when you call it, call it like this:
cMethod(self);
then, you would be able to write:
[param objcMethod];
In your cMethod.
This is because the self variable is a special parameter passed to Objective-C methods automatically. Since C methods don't enjoy this privilege, if you want to use self you have to send it yourself.
See more in the Method Implementation section of the programming guide.
I know your question is already answered by Aviad but just to add to the info since this is not unrelated:
In my case I needed to call an Objective-C method from a C function that I did not call myself (a Carbon Event function triggered by registering a global hotkey event) so passing self as a parameter was impossible. In this particular case you can do this:
Define a class variable in your implementation:
id thisClass;
Then in your init method, set it to self:
thisClass = self;
You can then call Objective-C methods from any C function in the class without the need to pass self as a parameter to the function:
void cMethod([some parameters]) {
[thisClass thisIsAnObjCMethod];
}
C function is not "inside of the self object". In fact, nothing is.
Objective-C methods effectively get self as an implicit argument, with magic done under the hood. For plain C functions, they aren't associated with any class or object, and there's no call magic, so no self. If you need it, you need to pass it to your C function explicitly as an argument.
To be totally truthful, there is no such thing as a C method. C has functions. To illustrate the difference, look at the following examples:
This is a working C program that defines a type and two functions that go along with it:
#include <stdio.h>
typedef struct foo_t {
int age;
char *name;
} Foo;
void multiply_age_by_factor(int factor, Foo *f) {
f->age = f->age * factor;
}
void print_foo_description(Foo f) {
printf("age: %i, name: %s\n", f.age, f.name);
}
int main() {
Foo jon;
jon.age = 17;
jon.name = "Jon Sterling";
print_foo_description(jon);
multiply_age_by_factor(2, &jon);
print_foo_description(jon);
return 0;
}
Here is an Objective-C implementation of that program:
#import <Foundation/Foundation.h>
#interface Foo : NSObject {
NSUInteger age;
NSString *name;
}
#property (nonatomic, readwrite) NSUInteger age;
#property (nonatomic, copy) NSString *name;
- (void)multiplyAgeByFactor:(NSUInteger)factor;
- (NSString *)description;
- (void)logDescription;
#end
#implementation Foo
#synthesize age;
#synthesize name;
- (void)multiplyAgeByFactor:(NSUInteger)factor {
[self setAge:([self age] * factor)];
}
- (NSString *)description {
return [NSString stringWithFormat:#"age: %i, name: %#\n", [self age], [self name]];
}
- (void)logDescription {
NSLog(#"%#",[self description]);
}
#end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Foo *jon = [[[Foo alloc] init] autorelease];
[jon setAge:17];
[jon setName:#"Jon Sterling"];
[jon logDescription];
[jon multiplyAgeByFactor:2];
[jon logDescription];
[pool drain];
return 0;
}
The output of the pure C program was:
age: 17, name: Jon Sterling
age: 34, name: Jon Sterling
The output of the Objective-C program was:
2009-08-25 17:40:52.818 test[8963:613] age: 17, name: Jon Sterling
2009-08-25 17:40:52.828 test[8963:613] age: 34, name: Jon Sterling
The only difference is all the junk that NSLog puts before the text. The functionality is exactly the same. So, in C, you can use something sort of like methods, but they are really just functions that include a pointer to a struct.
I don't think this answered your original question, but it did clear up some terminology issues you appear to have been having.
Another option to the answers given thus far is to use the objc_msgSend() function provided by the Objective-C runtime.

Objective-C Imports, primitive types with Cygwin

I understand the basic syntax of Objective-C, have installed Cygwin, and want to experiment. However i am unsure of two things:
What i would import, and
what the primitive type names are.
Can someone help me?
The only object you can inherit from is called Object. Bare in mind that this offers nowhere near the same amount of functionality as NeXTStep's or Cocoa's NSObject. Object does not even have anything like reference counting. In order to get the same sort of reference counting memory management that NSObject has you'll need to implement it yourself.
#import <objc/Object.h>
#interface MyObject : Object
{
int retainCount;
}
- (id) retain;
- (int) retainCount;
- (void) release;
#end
#implementation MyObject
+ (MyObject *) alloc
{
// In Cocoa, allocated objects have an implicit retain.
MyObject *anObject = [super alloc];
anObject->retainCount = 1;
return anObject;
}
- (void) release
{
retainCount--;
if (retainCount == 0)
[self free];
}
- (id) retain
{
retainCount++;
return self;
}
- (int) retainCount
{
return retainCount;
}
#end
int main (int argc, char *argv[])
{
MyObject *test = [[MyObject alloc] init];
[test retain];
[test release];
[test release];
// (test should be deallocated now)
return 0;
}
When linking, you have to make sure you link with -lobjc, this is where the definition of Object lies (I think).
The other big catch is with static string instances, i.e. strings in code that appear #"like this". With the GNU runtime, static instances of strings need to have a particular ivar layout, which is:
// Let's assume that we have a protocol <MyObject> that defines all the basic methods
// like retain, release etc. In this case, these should be no-ops because the static
// string is never deallocated. In Cocoa, there is a protocol <NSObject> which provides
// the same common methods.
#interface MyStaticStringClass : Object <MyObject>
{
char *str;
unsigned len;
}
- (const char *) cString;
#end
#implementation MyStaticStringClass
- (void) retain
{
return;
}
- (id) retain
{
return self;
}
- (int) retainCount
{
return INT_MAX;
}
- (const char *) cString
{
return str;
}
#end
int main (int argc, char *argv[])
{
id aString = #"Hello world!";
fprintf (stdout, "aString has the contents: %s\n", [aString cString]);
return 0;
}
When compiling, you can use the flag -fconstant-string-class=MyStaticStringClass. You can provide whatever methods you like for the string class but it must have only two ivars and they must be in the right order. If you don't want to use Objective-C style strings, then you don't have to define a static string class. If you do define a static string class it should be able to replicate the behaviour of your dynamic string class (i.e. string objects that are allocated during run time) so that you can use either in a given situation.
For command-line utilities and basic apps I choose not to use Cocoa or GNUstep but rather define my own classes. It has many drawbacks, but I find that object abstraction and metamorphism in Objective-C is much easier to implement than in the other languages that I program in.