Objective c 使用托管动态存储对简单程序进行分段故障处理

Objective c 使用托管动态存储对简单程序进行分段故障处理,objective-c,gnustep,Objective C,Gnustep,我试着问过几个我认识的人,但他们可能太忙了,没时间给我提建议 我一直在用alloc/dealoc的方式碰壁 具有下面的一个让我抓狂。。。这是浓缩的精华 我整个星期都在调试一些代码 以下是我认为应该发生的事情(但显然不是): 我分配一个游泳池 我创建了一个对象并自动释放以将其放入当前池中,以便 当我释放池时,它将解除锁定 测试类具有仅为内部的NSString变量 NSString在该类的dealoc方法中释放 我释放了池,它会释放测试对象 一旦尝试释放,它就会在dealoc方法中隔离故障 NSS

我试着问过几个我认识的人,但他们可能太忙了,没时间给我提建议

我一直在用alloc/dealoc的方式碰壁 具有下面的一个让我抓狂。。。这是浓缩的精华 我整个星期都在调试一些代码

以下是我认为应该发生的事情(但显然不是):

  • 我分配一个游泳池
  • 我创建了一个对象并自动释放以将其放入当前池中,以便 当我释放池时,它将解除锁定
  • 测试类具有仅为内部的NSString变量
  • NSString在该类的dealoc方法中释放
  • 我释放了池,它会释放测试对象
  • 一旦尝试释放,它就会在dealoc方法中隔离故障 NSString
在过去,我一直设法通过摆弄来购买,直到问题消失。但是,我现在已经到了开发阶段,需要证明我已经消除了存储问题

去年,我阅读了大量关于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>
我们非常欢迎您的建议,非常感谢。

问题在于:

cmdline = [NSString stringWithCString: "This is a test"];

您没有保留该对象,因此它实际上是以0 retain计数返回的,并很快自动删除。

您的字符串将被双重释放<代码>+[NSString stringWithCString:创建自动删除的对象。它会自动放入最近的自动释放池中

当池被释放时,字符串也被释放。然后,字符串的所有者再次发送
release
,这会导致异常。(这两种情况实际上可能以任意顺序发生;这无关紧要。)

从引用计数的角度来看,您的
命令
对象实际上并不拥有该字符串,因为它没有遵循NARC规则。它没有在字符串上使用任何
new
alloc
retain
copy
。自动释放池是唯一所有者。因此,
命令
稍后发送
释放
是错误的


解决方案是在创建自动释放字符串时将
retain
发送到该字符串,这样池和
命令都将拥有所有权,并且需要在以后发送
release
,或者使用
alloc
创建它,如
[[NSString alloc]initWithCString:
。那么,
命令将是唯一的所有者。

其中可怕的部分是。。。如何知道为类中的内部使用而创建的对象何时已自动删除或保留,何时未自动删除或保留?我认为一般的规则是,如果你分配它,你就会释放它。按照惯例。如果使用
new
alloc
创建它,则它是一个自有引用。如果你不这样做,那么这就不是你的问题(但实际上,它几乎肯定在自动释放池中)。规则是,如果您使用
alloc
分配它,GNUStep文档的相关部分似乎在这里:谢谢。使用修改后的助记符,我将开始构建返回到原始的、更复杂的代码的方法。在原始版本中,通过拆分创建的字符串数组通过连接连接到新行中,然后存储该行。我使用initWithCString在更简单的上下文中复制segfault。稍后我可能会带着更多的问题回来,所以请耐心等待。我真的需要把这件事的逻辑告诉我。我有一个相当大的任务关键型项目,时间紧迫。当然,这可能也是大家每天坐的地方。苹果也有很好的写作技巧://developer.Apple.com/library/mac/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html很高兴我能帮上忙。祝你好运
cmdline = [NSString stringWithCString: "This is a test"];