我有一个由Erica Sadun创建的类代码片段,仪器说它正在泄漏:
- (void)cacheBeginPointForTouches:(NSSet *)touches
{
if ([touches count] > 0) {
for (UITouch *touch in touches) {
CGPoint *point = (CGPoint *)CFDictionaryGetValue(touchBeginPoints, touch);
if (point == NULL) {
point = (CGPoint *)malloc(sizeof(CGPoint));
CFDictionarySetValue(touchBeginPoints, touch, point);
}
*point = [touch locationInView:self.superview];
}
}
}
仪器指向
point = (CGPoint *)malloc(sizeof(CGPoint));
作为泄漏线。
因为这个malloc的东西对我来说并不熟悉。我知道它分配内存,但由于我从未使用C,C ++和其他C语言,malloc和我不是熟人。
另一个我不明白的问题是她为什么在“点”之前加上星号
*point = [touch locationInView:self.superview];
那么,您是否看到代码有问题以及为什么乐器会说它泄漏了?关于星号的解释是一个奖励! :)
感谢。
答案 0 :(得分:5)
malloc
的规则非常简单。完成内存后,你应该使用free(pointer)
释放内存。因此,在代码中的某个时刻,字典将用于获取CGPoints。如果您的程序在此之后没有执行任何操作(并且指针已从字典中删除),则应在其上调用free(point)
。
该行
*point = ...;
表示:将...
放在内存中的位置,由point
指向。字典包含这些指向CGPoint值的指针,正如您所见,您可以轻松地首先存储指针,然后只填充指向的内存(尽管我必须承认,这不是很直观)
答案 1 :(得分:3)
代码段泄漏,因为它不完整。它的作用是为CGPoint对象分配内存。当它不再使用时必须免费。你已经省略了那部分。
在这种情况下,CGPoint对象似乎将在CFDictionary中使用。所以应该有代码来确定何时再次释放它是安全的。
答案 2 :(得分:2)
猜测,您可能没有正确创建字典。常规字典认为您将使用CFRetain / CFRelease模式来保留对象 - 但是,您可以附加使用您自己的内存管理方案的备用处理程序。
您应该检查代码中的CFDictionaryNew()调用,并确保它与Erica中的调用匹配。我怀疑她有valueCallbacks的自定义值,而你可能没有。
答案 3 :(得分:1)
在不知道上下文的情况下,我猜测编译器不喜欢没有检查malloc是否失败(malloc =内存分配,它抓取可用内存并将其分配给程序变量)。此外,这个片段本身并不释放malloc内存(虽然我假设这是在其他地方完成的。)
此外,“*”取消引用该值。例如,在标准C中,如果我写:
int val = 1;
int *p = &val;
printf("%d\n",*p);
*p = 2;
printf("%d\n",*p);
我会得到:
1
2
*允许您引用指针指向的对象。在上面的例子中,“p”是一个指针,但“* p”是指针引用的实际值(“val”)。
答案 4 :(得分:1)
malloc()和free()类似于Objective-C中的[NSObject alloc]和[NSObject release]。 malloc()分配内存并返回一个指针。 free()告诉操作系统不再需要内存。根据定义,没有free()的malloc()是内存泄漏。
这里不清楚是否存在实际的内存泄漏,因为指针存储在字典中。当字典被销毁时,或者当该键的值被覆盖时,必须释放内存。
关于这一行:
*point = [touch locationInView:self.superview];
它接受locationInView的返回值:并将其存储在point指向的地址。 “*”有解除引用运算符。
答案 5 :(得分:0)
我纯粹在这里猜测,假设该函数被命名为“cache”BeginPointForTouches,看起来这个函数的目的是创建一个触摸字典并缓存它们以便快速查找。作为一个缓存,看起来它是在程序的整个生命周期中保持其内存并且从不释放自己的那种。所以要确保在程序中或程序退出后是否发生此泄漏?如果之后,那么我所描述的可能并不是真正的泄漏。