NSString 的内存泄漏

发布于 2024-11-19 07:43:03 字数 1279 浏览 2 评论 0原文

我在这里阅读了几乎所有关于涉及 NSStrings 的内存管理的问题,但我无法真正解决这个问题。

@接口:

@property (nonatomic, retain) NSString *criticalTranscription;

@实现: viewDidLoad:

criticalTranscription = [[NSString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}
[transcription setText:criticalTranscription];

@XIB 一个带有 IBAction 的 UISegmentedControl 链接到:

- (IBAction) changeText:(id)sender
{
  if(transcriptionSelector.selectedSegmentIndex == 1)
    [transcription setText:diplomaticTranscription];
  else
    [transcription setText:criticalTranscription];
}

当我更改 UISegmentControl 的值时(加载后第一件事,没有其他运行),我遇到了这个错误(NSZombieEnabled=YES):

2011-07-07 01:10:43.639 Transcribe[404:707] *** -[CFString length]: message sent to deallocated instance 0x1189300

我在回溯中看不到任何相关内容。如果没有 NSZombieEnabled, criticalTranscription 仅指向随机数组或其他内容。没有进一步使用该变量或任何版本。

我进行了分析,没有发现任何可疑的泄漏。

有什么问题吗?

I read almost every Question here on SO about memory management that involves NSStrings, but I can't really solve this problem.

@interface:

@property (nonatomic, retain) NSString *criticalTranscription;

@implementation:
viewDidLoad:

criticalTranscription = [[NSString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}
[transcription setText:criticalTranscription];

@XIB
A UISegmentedControl with an IBAction linked to:

- (IBAction) changeText:(id)sender
{
  if(transcriptionSelector.selectedSegmentIndex == 1)
    [transcription setText:diplomaticTranscription];
  else
    [transcription setText:criticalTranscription];
}

When I change the value of the UISegmentControl (first thing right after loading, nothing else runs), I run into this error (NSZombieEnabled=YES):

2011-07-07 01:10:43.639 Transcribe[404:707] *** -[CFString length]: message sent to deallocated instance 0x1189300

I can't see anything relevant in the backtrace. Without NSZombieEnabled criticalTranscription just points to random arrays or something else. There is no further usage of the variable or any releases.

I ran analyze without any suspicious leaks.

What's the problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

问题在于您正在用您不拥有的字符串覆盖对您拥有的字符串的引用。

// you own the empty string returned here
criticalTranscription = [[NSString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    // immediately overwrite allocated instance (that you own)
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}

但是,不要使用这种方法,因为它会用不必要的字符串污染自动释放池。相反,使用可变字符串并将字符串附加到单个可变字符串实例。

此外,为了利用该属性的内置内存管理,您需要使用 self.riticalTranscription 而不仅仅是 riticTranscription。如果没有 self.,您将直接使用实例变量。

The problem is that you are overwriting a reference to a string that you own with one that you don't own.

// you own the empty string returned here
criticalTranscription = [[NSString alloc] init]; 

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    // immediately overwrite allocated instance (that you own)
    criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];
}

However, don't use this approach, because it pollutes the autorelease pool with unnecessary strings. Instead, use a mutable string and append strings to the single mutable string instance.

Also, in order to utilise the property's built-in memory management, you need to use self.criticalTranscription and not just criticalTranscription. Without the self., you are using the instance variable directly.

荒人说梦 2024-11-26 07:43:03

在 for 循环中,

criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];

您将 CriticalTranscription 设置为自动释放的字符串对象,但不保留它,从而导致火焰死亡。

您可以保留它或使用 @property(nonatomic, copy)NSString *riticTranscription; 的属性,并使用该属性而不是 ivar。

In your for loop

criticalTranscription = [criticalTranscription stringByAppendingString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
criticalTranscription = [criticalTranscription stringByAppendingString:@"\n\n"];

you are setting criticalTranscription to an autoreleased string object but not retaining it, thus the flaming death.

You could retain it or use a property with @property(nonatomic, copy)NSString *criticalTranscription; and use the property rather than the ivar.

安穩 2024-11-26 07:43:03

两个问题:

  • 您泄漏了字符串的第一个实例
  • 您分配给它的每个后续值都将被自动释放

要解决此问题,最简单的方法是将 CriticalTranscription 更改为 NSMutableString。然后你可以这样做:

criticalTranscription = [[NSMutableString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    [criticalTranscription appendString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    [criticalTranscription appendString:@"\n\n"];
}
[transcription setText:criticalTranscription];

…或者,

[criticalTranscription appendFormat:@"%@\n\n", [[paragraphs objectAtIndex:i] valueForKey:@"p"]];

另请注意,一旦完成,你需要在 riticTranscription 上调用 release,无论是在 - 的末尾viewDidLoad 或其相应的-viewDidUnload 中。

Two problems:

  • You’re leaking the first instance of the string
  • Every subsequent value you assign to it is getting autoreleased

To fix it, the easiest way is to change criticalTranscription to an NSMutableString. Then you can do:

criticalTranscription = [[NSMutableString alloc] init];

NSArray *paragraphs = [doc valueForKeyPath:@"critical.text"];
for(int i = 0; i < [paragraphs count]; i++) 
{
    [criticalTranscription appendString:[[paragraphs objectAtIndex:i] valueForKey:@"p"]];
    [criticalTranscription appendString:@"\n\n"];
}
[transcription setText:criticalTranscription];

…alternatively,

[criticalTranscription appendFormat:@"%@\n\n", [[paragraphs objectAtIndex:i] valueForKey:@"p"]];

Also note that you need to call release on criticalTranscription once you’re done with it, either at the end of your -viewDidLoad or in its corresponding -viewDidUnload.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文