我试过问过几个我认识的人,但他们可能太忙了,无法就此提出建议。
我一直在使用alloc / dealloc的方式进入墙 用。下面的一个让我疯狂......这是一个简单的本质 我一直试图调试的一些代码。
以下是我认为应该发生的事情(但显然不是):
在过去,我设法通过摆弄来购买,直到问题消失。但是,我现在已经达到了发展的程度,我需要能够证明我已经消除了存储问题。
去年我读过大量关于ObjC存储管理的文档。 不幸的是,似乎在这一切实际上如何适应方面存在一些分歧 这些混乱对我们这些没有参与的人没有帮助 随着它的发展,这个托管存储过程。如果我遇到困难(我曾经在RTOS的汇编代码中编写DSA),我只能想象其他人必须面对的问题。
一个非常有用的东西是关于如何测试代码以消除的手册 这种错误。我确信这样的信息存在,并且在这里有点碰到,但是这些碎片并不是整齐地融合在一起。我也一直在使用enableDoubleReleaseCheck。
我把它留下来以保持测试用例的简单。
这是CommandTest.m,一个完整的测试用例,结果如下:
./CommandTest
Release cmdline
Segmentation fault (core dumped)
/* Makefile strings:
OBJC = gcc -g -fobjc-exceptions -fconstant-string-class=NSConstantString -D_NATIVE_OBJC_EXCEPTIONS -I /usr/include/GNUstep
CommandTest: CommandTest.o $(OBJC) -g -o CommandTest CommandTest.o -lobjc -lgnustep-base */
#include <stdio.h>
@interface Command:NSObject {NSString *cmdline;}
- (id) init;
- (void) dealloc;
@end
@implementation Command
- (id) init {
if (!(self = [super init])) {return nil;}
cmdline = [NSString stringWithCString: "This is a test"];
return self;
}
- (void) dealloc {
printf ("Release cmdline\n");
[cmdline release];
printf ("Release cmdline done\n");
[super dealloc];
}
@end
int main( int argc, char *argv[] ) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Command *cmd = [[Command new] autorelease];
@try {[pool release];}
@catch (NSException *e){
printf ("Fatal [%s] %s\n", [[e name] cString], [[e reason] cString]);}
printf ("Done\n");
exit (EXIT_SUCCESS);
}
建议将 欢迎并非常感谢。
答案 0 :(得分:2)
你的字符串被双重释放。 +[NSString stringWithCString:]
创建一个自动释放的对象。它会自动放入最近的自动释放池中。
释放池时,字符串也是如此。然后,字符串的所有者再次发送release
,这会导致您的异常。 (这两个实际上可能以任何顺序发生;无关紧要。)
从引用计数的角度来看,您的Command
对象实际上并不拥有该字符串,因为它没有遵循NARC规则。它未在字符串中使用任何new
,alloc
,retain
或copy
。自动释放池是唯一的所有者。因此,Command
以后发送release
是错误的。
解决方案是在创建时将retain
发送到自动释放的字符串 - 然后池和Command
都拥有所有权,并且需要稍后发送release
- 或使用alloc
创建,如[[NSString alloc] initWithCString:]
中所示。然后Command
将是唯一所有者。
答案 1 :(得分:1)
问题出在这里:
cmdline = [NSString stringWithCString: "This is a test"];
你没有保留这个对象,所以它有效地返回0保留计数并且很快就会自动释放。