Random Number Objective-C (linux) - objective-c

Now, I know that this is a simple question for MacOS, but when I compile a code with 'arc4random % n' in it, I just get an error log in Terminal saying:
main.m:9: error: ‘arc4random’ undeclared (first use in this function)
main.m:9: error: (Each undeclared identifier is reported only once
main.m:9: error: for each function it appears in.)
and I use:
gcc `gnustep-config --objc-flags` -lgnustep-base main.m -o main
to compile it
and here's my code (if it helps) :
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int number, guess;
number = arc4random() % 101;
while (!guess == number) {
NSLog (#"Please guess a number between 1 and 100");
scanf ("%i", &guess);
if (guess < number) {
NSLog (#"Sorry, guessed too low!");
}
else if (guess > number) {
NSLog (#"Sorry, guessed too high!");
}
}
NSLog (#"You guessed correct!");
[pool drain];
return 0;
}

You may consider using clang instead of gcc
Use
clang -fno-objc-arc main.m -framework Foundation -o main
Also I'd use arc4random_uniform(101) instead of arc4random() % 101, since the former is bias free.

A few things:
Your use of >> and <<, these are not valid comparison operators. This will compile, but not perform what you expect. You either need to use > (greater than), >= (greater than or equals), < (less than) or <= (less than or equals).
Your compile error is due to your use of arc4random. This is a function, but you've not used it as such. You need to change your line to
number = arc4random() % 101;
Not 100% sure on this, but %i in your scanf looks like it should be %d

Related

Apple Mach-0 linker error duplicate

I have written a straight forward program, but getting duplicate symbol linker error (error below) There is nothing additional in the .h file excepting for the #interface Fraction : NSObject #end
I am rather new to xcode.
//SAMPLE CODE
#import "JTViewController.h"
#interface Fraction ()
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
#end
#implementation Fraction
{
int numerator;
int denominator;
}
-(void) print
{
NSLog (#"%i/%i", numerator, denominator);
}
-(void) setNumerator:(int)n
{
numerator = n;
}
-(void) setDenominator:(int)d
{
denominator = d;
}
#end
int main (int argc, char * argv[])
{
#autoreleasepool {
// Create an instance of Fraction and initialise it
Fraction *myFraction = [[Fraction alloc] init];
//Set Fraction to 1/3
[myFraction setNumerator: 1];
[myFraction setDenominator: 3];
//Display the fraction using the print method
[myFraction print];
}
return 0;
}
This is the error
Ld /Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Products/Debug-iphonesimulator/BrandNew.app/BrandNew normal i386
cd /Users/jamesmurray/AppsDev/BrandNew
setenv IPHONEOS_DEPLOYMENT_TARGET 6.1
setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch i386 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk -L/Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Products/Debug-iphonesimulator -F/Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Products/Debug-iphonesimulator -filelist /Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Intermediates/BrandNew.build/Debug-iphonesimulator/BrandNew.build/Objects-normal/i386/BrandNew.LinkFileList -Xlinker -objc_abi_version -Xlinker 2 -fobjc-arc -fobjc-link-runtime -Xlinker -no_implicit_dylibs -mios-simulator-version-min=6.1 -framework UIKit -framework Foundation -framework CoreGraphics -o /Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Products/Debug-iphonesimulator/BrandNew.app/BrandNew
duplicate symbol _main in:
/Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Intermediates/BrandNew.build/Debug-iphonesimulator/BrandNew.build/Objects-normal/i386/main.o
/Users/jamesmurray/Library/Developer/Xcode/DerivedData/BrandNew-akqlirretjwoeuaqkrwlbqmlqxlc/Build/Intermediates/BrandNew.build/Debug-iphonesimulator/BrandNew.build/Objects-normal/i386/JTViewController.o
ld: 1 duplicate symbol for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have no idea where it came from. Any assistance would be appreciated.
Like the linker error says, you have two main() functions; one in main.m and one in JTViewController.m.
Remove the one in JTViewController.m (move the functionality into main.m).
There is nothing special about main here. You can only have one globally visible non-common symbol in your object files. Non-static functions are globally visible and non-common symbols, hence you can only have a function with a specific name defined only once. For example:
a.c:
int func() { ... }
b.c:
void func(int arg) { ... }
When both files are compiled, it creates two globally visible symbols with the name of func (with whatever decoration the compiler might apply to the symbol), despite the difference in the argument lists and the return types. As the linker tries to resolve all symbol references in order to produce the final executable, it faces the hard choice of selecting the right version of func, so it takes the most direct approach - simply gives you an error about duplicate symbol definition and bails out.
This is not a requirement unique to the C language (and Objective-C is basically a runtime extension of C) as it is imposed by the system linker. It also translates to many other languages like Objective-C, C++, Fortran, Pascal, etc. In C++ function symbols are decorated according to the namespace they live in and the list of their arguments (the former enables function overloading), but again one cannot have two functions with the same list of arguments in the same namespace defined in different source files.
Usually C and C++ functions are compiled to globally visible symbols unless the static modifier is applied:
a.c:
static int func() { ... }
b.c:
void func(int arg) { ... }
This would not result in a global symbol func in a.o clashing with the one in b.o and the linker would not complain. It would also work if rather func in b.c is given the static treatment or if both functions are static.

Using constant to declare an array of item

Is it possible to use some thing like this in Objective-C:
#define number_of_items 10
and then using it as:
int arr[number_of_items];
Yes, assuming you mean Objective C. It's pretty much a superset of "proper" C so this is perfectly okay. It's also okay in both C and C++.
You can see that it works in the following transcript:
pax> cat qq.m
#import <objc/Object.h>
// First method.
#define number_of_items 10
int arr[number_of_items];
// Second method.
#define NUMBER_OF_ROWS 10
#interface test : Object{ int xyzzy[NUMBER_OF_ROWS]; }
#end;
pax> vi qq.m ; gcc -o qq.o -c qq.m -lobjc
pax> # no errors occurred
And, now that we've finally seen what you're actually using:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define NUMBER_OF_ROWS_ (IS_IPAD? 18: 18)
NUMBER_OF_ROWS_ is not a constant, since it depends on the return value of the function UI_USER_INTERFACE_IDIOM().
In other words, it cannot be calculated at compile time. That's why you're getting the error. You can see this by compiling the following code:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define NUMBER_OF_ROWS_ (IS_IPAD ? 18: 20)
int UI_USER_INTERFACE_IDIOM(void) {return 20;}
int UIUserInterfaceIdiomPad;
int main (void) {
int arr[NUMBER_OF_ROWS_];
return 0;
}
Under gcc --pedantic, you get:
qq.m: In function ‘main’:
qq.m:8: warning: ISO C90 forbids variable length array ‘arr’
You either need to use a dynamically adjustable collection like NSMutableArray or use an array of the maximum size desired and only use what you need of that.

Weird error NSAssert

I can't figure out why I get
use of undeclared identifier _cmd did you mean rcmd
on the line where NSAssert is.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int x = 10;
NSAssert(x > 11, #"x should be greater than %d", x);
[pool drain];
return 0;
}
Inside every Objective-c method there are two hidden variables id self and SEL _cmd
so
- (void)foo:(id)bar;
is really
void foo(id self, SEL _cmd, id bar) { ... }
and when you call
[someObject foo:#"hello world"]
it is actually
foo( someObject, #selector(foo), #"hello world")
If you cmd-click on NSAssert to jump to it's definition you will see that it is a macro that uses the hidden _cmd variable of the method you are calling it from. This means that if you are not inside an Objective-c method (perhaps you are in 'main'), therefore you don't have a _cmd argument, you cannot use NSAssert.
Instead you can use the alternative NSCAssert.
NSAssert is only meant to be used within Objective-C methods. Since main is a C function, use NSCAssert instead.
Try to replace
NSAssert(x > 11, [NSString stringWithFormat:#"x should be greater than %d", x]);
with
NSCAssert(x > 11, [NSString stringWithFormat:#"x should be greater than %d", x]);
You have to wrap your string in a NSString class if you want to use format parameters. That is because #"" is a default constructor for a plain NSString. The way it is written now gives a third parameter to the NSAssert function and messes with it.
NSAssert(x > 11, [NSString stringWithFormat:#"x should be greater than %d", x]);
TL;DR - stick with stray NSAssert() - don't try this in production
Original code
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int x = 10;
NSAssert(x > 11, #"x should be greater than %d", x);
[pool drain];
return 0;
}
Build failure
Compiling file hello.m ...
hello.m:9:5: error: use of undeclared identifier '_cmd'
NSAssert(x > 11, #"x should be greater than %d", x);
^
/usr/include/Foundation/NSException.h:450:32: note: expanded from macro 'NSAssert'
handleFailureInMethod: _cmd \
^
hello.m:9:5: error: use of undeclared identifier 'self'
/usr/include/Foundation/NSException.h:451:17: note: expanded from macro 'NSAssert'
object: self \
^
2 errors generated.
Based on explanation by #hooleyhoop #Robert and
id
self
SEL,
the following dirty hack may be applicable if I insist on using
NSAssert() instead of
NSCAssert()
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int x = 10;
// Dirty hack
SEL _cmd=NULL;
NSObject *self=NULL;
NSAssert(x > 11, #"x should be greater than %d", x);
[pool drain];
return 0;
}
Build & run
Compiling file hello.m ...
Linking tool hello ...
2021-03-04 21:25:58.035 hello[39049:39049] hello.m:13 Assertion failed in (null)(instance), method (null). x should be greater than 10
./obj/hello: Uncaught exception NSInternalInconsistencyException, reason: hello.m:13 Assertion failed in (null)(instance), method (null). x should be greater than 10
Hooray it works! But, alas, please stay away from it :)

Can't compile Objective-C code with clang

I get following error with following Objective-C code, while trying to compile it with clang.
Obj-C Code:
// first program example
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
#autoreleasepool {
NSLog (#"Programming is fun!");
}
return 0;
}
Error message:
main.m:6:5: error: unexpected '#' in program
#autoreleasepool {
^
main.m:7:38: error: extraneous ')' before ';'
NSLog (#"Programming is fun!");
^
main.m:7:16: warning: expression result unused [-Wunused-value]
NSLog (#"Programming is fun!");
^~~~~~~~~~~~~~~~~~~~~~
main.m:9:5: error: expected identifier or '('
return 0;
^
main.m:10:1: error: expected external declaration
}
^
1 warning and 4 errors generated.
I can compile without error within XCode.
Clang info:
Apple clang version 2.1 (tags/Apple/clang-163.7.1) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.3.0
Thread model: posix
You need clang v3.0 or greater to use #autoreleasepool.
Supposing you have clang 3.0 on your system path you can compile your code with:
clang -Wall -framework Foundation prog_name.m -o prog_name
You'll need to upgrade your Clang; the #autoreleasepool{} directive was released at the same time as ARC, and requires v3.0 or greater.

Why does backtrace not contain Objective-C symbols regardless of -rdynamic?

Update: I'm working with the GNU-runtime on Linux. The problem does not occur on MacOS with the Apple-runtime.
Update 2: I compiled the GNU-runtime on MacOS and build the example with it. The error does not occur on MacOS with the GNU-runtime. I would say the problem is the glibc (since backtrace and backtrace_symbols are glibc extensions).
When printing a backtrace in a GCC compiled Objective-C app using backtraceand backtrace_symbols, I don't get any Objective-C symbols. Only the filenames, addresses and C-symbols appear.
I compiled with -g and linked with -rdynamic.
My test app:
void _printTrace()
{
void *addr[1024];
int aCount = backtrace(addr, 1024);
char **frameStrings = backtrace_symbols(addr, aCount);
for (int i = 0; i < aCount; i++) {
printf("%s\n", frameStrings[i]);
}
free(frameStrings);
}
#interface TheObject
+ (void)_printTrace;
+ (void)printTrace;
#end
#implementation TheObject
+ (void)_printTrace
{
_printTrace();
}
+ (void)printTrace
{
[self _printTrace];
}
#end
void printTrace()
{
[TheObject printTrace];
}
int main(int argc, char **argv)
{
printTrace();
return 0;
}
and it's output:
./test.bin(_printTrace+0x1f) [0x8048e05]
./test.bin() [0x8048e60]
./test.bin() [0x8048e8b]
./test.bin(printTrace+0x34) [0x8048ec5]
./test.bin(main+0xf) [0x8048eda]
/lib/libc.so.6(__libc_start_main+0xe5) [0xb7643bb5]
./test.bin() [0x8048b51]
Is there a way to let the Objective-C symbols appear in this backtrace?
dladdr() only reports global and weak symbols. But all Objective-C function symbols are local:
$ readelf -s so_backtrace
Symbol table '.dynsym' contains 29 entries:
…
Symbol table '.symtab' contains 121 entries:
Num: Value Size Type Bind Vis Ndx Name
…
49: 08048a01 13 FUNC LOCAL DEFAULT 14 _c_TheObject___printTrace
50: 08048a0e 47 FUNC LOCAL DEFAULT 14 _c_TheObject__printTrace
…
You can verify that local symbols are never returned by looking at the GNU libc source code yourself. backtrace_symbols() is defined in sysdeps/generic/elf/backtracesyms.c. It relies on _dl_addr(), which is defined in elf/dl-addr.c, to provide it with the symbol names. That ultimately calls determine_info(). If it can, it uses the the GNU hash table, which does not include local symbols by design:
49 /* We look at all symbol table entries referenced by the hash
50 table. */
…
60 /* The hash table never references local symbols so
61 we can omit that test here. */
If the GNU hash table isn't present, it falls back to standard hash table. This includes all the symbols, but the determine_info() code filters out all but the global symbols and weak symbols:
90 if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
91 || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
To symbolicate the Objective-C function addresses, you would have to perform the look-up yourself and not filter out the local function symbols. Further, you would have to demangle the Objective-C function symbols to restore _c_TheObject___printTrace to +[TheObject _printTrace].
GNUstep's NSException implementation doesn't use backtrace, instead it uses libbfd (binary file descriptor). I think the function that actually does the work is called static void find_address, which you can view here. Using this trivial example, I get the results that follow.
#include <Foundation/Foundation.h>
#interface Test : NSObject {}
+ (void) test;
#end
#implementation Test
+ (void) test
{
Class GSStackTrace = objc_getClass("GSStackTrace");
id stack = [GSStackTrace currentStack];
for (int i = 0; i < [stack frameCount]; i++)
{
NSLog (#"%#", [[stack frameAt:i] function]);
}
}
#end
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[Test test];
[pool release];
return 0;
}
Output (when compiled with debug symbols):
2010-10-18 14:14:46.188 a.out[29091] +[GSStackTrace currentStack]
2010-10-18 14:14:46.190 a.out[29091] +[Test test]
2010-10-18 14:14:46.190 a.out[29091] main
2010-10-18 14:14:46.190 a.out[29091] __libc_start_main
You may be able to pick apart GSStackTrace. It is a “private” class (that's why I need to use objc_getClass, you'll also get lots of unrecognised selector warnings), but it seems to contain all the code necessary to read Objective-C class names.
Tested on Ubuntu 9.04 with GNUstep configured with --enable-debug (so that GSFunctionInfo is included in the build).
I expect you'll need to ask the ObjC run time about the addresses to get symbol information. The addresses returned from backtrace() could probably be passed to something like object_getClass() to get the class, for example. I haven't tried any of this but it's where I'd look next in this case.