0

I followed this gnustep setup.

The source contains an almostempty autoreleasepool. Without it, the application works like standard c.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"Hello, World!");
    }

    return 0;
}

Make:

CC=clang
CXX=clang++

OPT_RELEASE=-O3 
OPT_DEBUG=-DDEBUG -g

INCLUDE=-I.
LIBRARY= -L/usr/local/lib

CFLAGS=`gnustep-config --objc-flags`  -fobjc-runtime=gnustep
LDFLAGS=`gnustep-config --base-libs` -fobjc-runtime=gnustep

SOURCES= hello.m

OBJECTS=$(SOURCES:.m=.o)

DEPENDENCIES=$(SOURCES:.m=.d)

EXECUTABLE=hello    

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS) 
        $(CC) $(LIBRARY) $(LDFLAGS) $(OBJECTS) $(STATICLIBS) -o $@

%.o: %.m
    $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

clean:
   rm -rf $(OBJECTS) $(EXECUTABLE) $(DEPENDENCIES) core

The core:

#0  0x0000000000000000 in ?? ()
#1  0x00007ffff71f5c06 in objc_autoreleasePoolPop () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#2  0x00007ffff7716753 in -[NSAutoreleasePool emptyPool] (self=0x77dd30, _cmd=0x7ffff7cf5010 <.objc_selector_list+128>) at NSAutoreleasePool.m:411
#3  0x00007ffff77168c4 in -[NSAutoreleasePool dealloc] (self=0x77dd30, _cmd=0x7ffff7cf4fa0 <.objc_selector_list+16>) at NSAutoreleasePool.m:729
#4  0x00007ffff771686c in -[NSAutoreleasePool release] (self=0x77dd30, _cmd=0x7ffff7cfc3c0 <.objc_selector_list+240>) at NSAutoreleasePool.m:722
#5  0x00007ffff7728ca9 in +[NSCalendarDate initialize] (self=0x7ffff7cfc1e0 <_OBJC_CLASS_NSCalendarDate>, _cmd=0x63b470) at NSCalendarDate.m:380
#6  0x00007ffff71e5e93 in objc_send_initialize () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#7  0x00007ffff71f3199 in objc_msg_lookup_sender () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#8  0x00007ffff71f2eb7 in slowMsgLookup () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#9  0x00007ffff71f5048 in objc_msgSend_fpret () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#10 0x00007ffff776d4c6 in +[NSDate initialize] (self=0x7ffff7d0afe0 <_OBJC_CLASS_NSDate>, _cmd=0x63b470) at NSDate.m:134
#11 0x00007ffff71e5e93 in objc_send_initialize () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#12 0x00007ffff71f3199 in objc_msg_lookup_sender () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#13 0x00007ffff71f2eb7 in slowMsgLookup () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#14 0x00007ffff71f5048 in objc_msgSend_fpret () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#15 0x00007ffff78cdb30 in +[NSUserDefaults initialize] (self=0x7ffff7d7b4a0 <_OBJC_CLASS_NSUserDefaults>, _cmd=0x63b470) at NSUserDefaults.m:563
#16 0x00007ffff71e5e93 in objc_send_initialize () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#17 0x00007ffff71f3199 in objc_msg_lookup_sender () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#18 0x00007ffff71f2eb7 in slowMsgLookup () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#19 0x00007ffff71f5048 in objc_msgSend_fpret () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#20 0x00007ffff780c632 in +[NSObject initialize] (self=0x7ffff7d3c460 <_OBJC_CLASS_NSObject>, _cmd=0x63b470) at NSObject.m:1144
#21 0x00007ffff71e5e93 in objc_send_initialize () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#22 0x00007ffff71e5b06 in objc_send_initialize () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#23 0x00007ffff71f3199 in objc_msg_lookup_sender () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#24 0x00007ffff71f2eb7 in slowMsgLookup () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#25 0x00007ffff71f5048 in objc_msgSend_fpret () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#26 0x00007ffff71f58df in initAutorelease () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#27 0x00007ffff71f56ad in objc_autoreleasePoolPush () from /usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#28 0x0000000000400a14 in main (argc=1, argv=0x7fffffffdbe8) at hello.m:5
echristopherson
  • 6,974
  • 2
  • 21
  • 31
Rudi Rüssel
  • 439
  • 4
  • 13
  • declaring a NSAutoreleasePool *pool works. – Rudi Rüssel Jan 15 '14 at 16:08
  • Why are there cursor controls in the sources (identified via od)? For example NSAutoreleasePool.m l. 248ff: [CTRL L] /* Functions for managing a per-thread cache of NSAutoreleasedPool's .. CTRL L = Shell: Clear Screen. – Rudi Rüssel Jan 15 '14 at 17:16
  • segmentation fault caused by DeleteAutoreleasePool(pool, SELECTOR(release)); called by libobjc2 in arc.m line 338 – Rudi Rüssel Jan 15 '14 at 17:34
  • Rudi: Ctrl-L is often used in source code (in my experience, usually in code created in Emacs) to indicate a page break, e.g. to separate out logical sections of the code. Traditionally that was the character that would cause a printer to start a new page. – echristopherson Jan 15 '14 at 22:40
  • echristopherson:Thank you for the info. Long, long time ago I used emacs for my thesis. But this was in another century. Today I'm using **pragma mark** for this. But marks are only useful for clang/XCode. – Rudi Rüssel Jan 16 '14 at 09:16

1 Answers1

1

So here is my research result:

DeleteAutoreleasePool is declared as IMP in libobjc2(arc.m) and called from objc_autoreleasePoolPop if no valid arc autorelease-pool was found in NSAutoreleasePool.m.

With an actual version of clang, NSAutoreleasePool correctly detects the availability of the release-pool. (declared in capabilities.h)

This explains why NSAutoreleasePool works.

arc.m in return reads this result. If the result is positive it does nothing, otherwise it calls the reference counting methods from NSAutoreleasePool (so GCC and other compilers can be used).

A defect in this process can be found in initAutorelease(arc.m). Here the availability of an autoreleasepool is detected with class_respondsToSelector. In other words a class method is used as feature-flag (sigh).

The validated method is defined as follows:

#ifdef ARC_RUNTIME
...

/**
 * Indicate to the runtime that we have an ARC-compatible implementation of
 * NSAutoreleasePool and that it doesn't need to bother creating objects for   
 * pools.
*/
- (void)_ARCCompatibleAutoreleasePool {}
#else

The problem with this function is:

  • It does not do anything.
  • It returns nothing.

Even with debug enabled I would expect that this function is ignored during compilation and also not exported as library call.

This explains why obj-arc (@autoreleasepool) does not work with clang 3.4+.

You can rewrite or simply deactivate this detection method if you only use clang for your objc projects.

Rudi Rüssel
  • 439
  • 4
  • 13