[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Crashing in _Block_release
From: |
Jens Alfke |
Subject: |
Re: Crashing in _Block_release |
Date: |
Wed, 29 Feb 2012 17:34:14 -0800 |
On Feb 29, 2012, at 3:45 PM, David Chisnall wrote:
> This looks like a double-free. Can you try running with valgrind or with
> whatever memory debugging facilities your system malloc provides turned on?
I ran with valgrind and it reported nothing until the point where the program
normally crashes; then it output:
==13971== Invalid read of size 4
==13971== at 0x4A88075: _Block_object_dispose (blocks_runtime.m:206)
==13971== by 0x47B0F28: __destroy_helper_block_ (MYBlockUtils.m:54)
==13971== by 0x4A88334: _Block_release (blocks_runtime.m:299)
==13971== by 0x414476B: _i_GSBlock__release (GSBlocks.m:81)
==13971== by 0x41C6DC0: _i_NSAutoreleasePool__emptyPool
(NSAutoreleasePool.m:658)
==13971== by 0x41C68E0: _i_NSAutoreleasePool__dealloc
(NSAutoreleasePool.m:538)
==13971== by 0x41C674F: _i_NSAutoreleasePool__drain (NSAutoreleasePool.m:519)
==13971== by 0x47B16C0: RunTestCase (Test.m:69)
==13971== by 0x47B1074: RunTestCaseNamed (Test.m:83)
==13971== by 0x47B1215: RunTestCases (Test.m:114)
==13971== by 0x8048751: main (EmptyGNUstepApp.m:29)
==13971== Address 0x748247c is 0 bytes after a block of size 20 alloc'd
==13971== at 0x402732C: calloc (vg_replace_malloc.c:467)
==13971== by 0x4A79075: alloc (gc_none.c:21)
==13971== by 0x4A87C33: _Block_object_assign (blocks_runtime.m:127)
==13971== by 0x47B0EDC: __copy_helper_block_ (MYBlockUtils.m:54)
==13971== by 0x4A87F89: _Block_copy (blocks_runtime.m:265)
==13971== by 0x41446EB: _i_GSBlock__copy (GSBlocks.m:71)
==13971== by 0x47B089F: MYAfterDelay (MYBlockUtils.m:29)
==13971== by 0x47B0BA1: Test_MYAfterDelay (MYBlockUtils.m:54)
==13971== by 0x47B157C: RunTestCase (Test.m:46)
==13971== by 0x47B1074: RunTestCaseNamed (Test.m:83)
==13971== by 0x47B1215: RunTestCases (Test.m:114)
==13971== by 0x8048751: main (EmptyGNUstepApp.m:29)
==13971==
The “__destroy_helper_block_” function must be something auto-generated by the
compiler; the source line (MYBlockUtils.m:54) is the line where the block
literal appears in my code.
I’ll paste my code below, with minimal changes to replace some of my own
testing and assertion macros with standard stuff. The crash is after the call
to the test function, when the test harness drains the temporary autorelease
pool. FYI, this code runs fine on Mac OS X 10.7 and iOS 5.
—Jens
@interface NSObject (MYBlockUtils)
- (void) my_run_as_block;
@end
/* This is sort of a kludge. This method only needs to be defined for blocks,
but their class (NSBlock) isn't public, and the only public base class is
NSObject. */
@implementation NSObject (MYBlockUtils)
- (void) my_run_as_block {
((void (^)())self)();
}
@end
id MYAfterDelay( NSTimeInterval delay, void (^block)() ) {
block = [[block copy] autorelease];
[block performSelector: @selector(my_run_as_block)
withObject: nil
afterDelay: delay];
return block;
}
void TestMYAfterDelay(void) {
__block BOOL fired = NO;
MYAfterDelay(0.5, ^{fired = YES; NSLog(@"Fired!");});
assert(!fired);
while (!fired) {
if (![[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
beforeDate: [NSDate
dateWithTimeIntervalSinceNow: 0.5]])
break;
}
assert(fired);
}