为什么 Instruments 说这段代码正在泄露?
我有来自 Erica Sadun 创建的类的代码片段,Instruments 说该代码正在泄漏:
- (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];
}
}
}
Instruments 指向
point = (CGPoint *)malloc(sizeof(CGPoint));
泄漏行。
因为这个 malloc 的东西我不熟悉。我知道它分配内存,但由于我从未使用过 C、C++ 和其他风格的 C,因此我和 malloc 并不熟悉。
我不明白的另一个问题是为什么她在“点”之前加了一个星号
*point = [touch locationInView:self.superview];
,所以,你看到代码有问题吗?为什么仪器说它在那里泄漏?关于星号的解释是一个奖励! :)
谢谢。
I have this snippet of code from a class created by Erica Sadun, that Instruments says is leaking:
- (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];
}
}
}
Instruments is pointing to
point = (CGPoint *)malloc(sizeof(CGPoint));
as the leaking line.
As this malloc stuff is not familiar to me. I know that it allocates memory, but as I never worked with C, C++ and other flavors of C, malloc and I are not acquaintances.
Another question I don't understand is why she put an asterisk before "point" on
*point = [touch locationInView:self.superview];
So, do you see something wrong with the code and why instruments are saying it is leaking there? An explanation about the asterisk is a bonus! :)
thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
malloc
的规则非常简单。使用完内存后,应该使用free(pointer)
释放它。因此,在代码中的某个时刻,字典将用于获取 CGPoints。如果您的程序在此之后对 CGPoints 不执行任何操作(并且指针已从字典中删除),您应该对它们调用free(point)
。该行的
意思是:将
...
放入内存中由point
指向的位置。字典包含这些指向 CGPoint 值的指针,正如您所看到的,您可以轻松地首先存储指针,然后才填充指向的内存(尽管,我必须承认,这不是很直观)The rules for
malloc
are quite simple. Once you're done with the memory, you should free it, usingfree(pointer)
. So at some point in your code, the dictionary will be used to get the CGPoints. If your program does nothing after this with the CGPoints (and the pointer is removed from the dictionary), you should callfree(point)
on them.The line
means to say: put
...
in the location in memory, pointed to bypoint
. The dictionary contains these pointers to your CGPoint values, and as you see you can easily first store the pointer, and only then fill the memory pointed to (although, I must admit, this is not very intuitive)代码片段正在泄漏,因为它不完整。它的作用是为 CGPoint 对象分配内存。当它不再使用时,必须将其释放。你省略了那部分。
在本例中,CGPoint 对象似乎在CFDictionary 中使用。因此应该有代码来确定何时可以安全地再次释放它。
The code snippet is leaking, because it is not complete. What it does is to allocate memory for a CGPoint object. This has to be free'd when it is no longer in use. You have omitted that part.
In this case, the CGPoint object seems to be used in the CFDictionary. So there should be code to determine when it is safe to free it again.
据猜测,您可能没有正确创建字典。常规字典认为您将使用 CFRetain/CFRelease 模式来保留对象 - 但是,您可以附加使用您自己的内存管理方案的备用处理程序。
您应该检查代码中的 CFDictionaryNew() 调用,并确保它与 Erica 的调用相匹配。我怀疑她有 valueCallbacks 的自定义值,而您可能没有。
At a guess, you have probably not created the dictionary properly. A regular dictionary thinks you'll be using the CFRetain/CFRelease pattern to hold on to objects - however, you can attach alternate handlers that use your own memory mamagement scheme.
You should check the CFDictionaryNew() call in your code and make sure it matches the one in Erica's. I suspect she has a custom value for valueCallbacks while you probably don't.
在不知道上下文的情况下,我猜测编译器不喜欢不检查 malloc 是否失败(malloc = 内存分配,它获取可用内存并将其分配给程序变量)。另外,这个片段本身并不会释放 malloc 的内存(尽管我假设这是在其他地方完成的)。
此外,“*”取消引用该值。例如,在标准 C 中,如果我写:
我会得到:
* 允许您引用指针所指向的对象。在上面的示例中,“p”是一个指针,但“*p”是指针引用的实际值(“val”)。
Without knowing the context, I'm guessing the compiler doesn't like that the there is no check to see whether or not malloc fails (malloc = memory allocation, it grabs available memory and assigns it to your program variable). Also, this snippet by itself does not free the malloc'd memory (although I'm assuming this is done elsewhere).
Also, the "*" dereferences the value. For example, in standard C, if I write:
I'd get:
The * allows you to reference the object to which the pointer is pointing. In the example above, "p" is a pointer, but "*p" is the actual value the pointer is referencing ("val").
malloc() 和 free() 就像 Objective-C 中的 [NSObject alloc] 和 [NSObject release] 一样。 malloc() 分配内存并返回一个指针。 free() 告诉操作系统不再需要该内存。根据定义,没有 free() 的 malloc() 会导致内存泄漏。
这里不清楚是否存在实际的内存泄漏,因为指针存储在字典中。当字典被销毁或该键的值被覆盖时,必须释放内存。
至于行:
它获取 locationInView: 的返回值并将其存储在 point 指向的地址处。那里的“*”是取消引用运算符。
malloc() and free() are like [NSObject alloc] and [NSObject release] in Objective-C. malloc() allocates memory and returns a pointer. free() tells the OS that the memory is no longer needed. A malloc() without a free() is then, by definition, a memory leak.
It's not clear here whether there is an actual memory leak, since the pointer is being stored in a dictionary. When the dictionary is destroyed, or when the value for that key is overwritten, the memory must be freed.
As for the line:
It takes the return value of locationInView: and stores it at the address pointed to by point. The "*" there is the dereferencing operator.
我在这里纯粹是猜测,鉴于该函数名为“cache”BeginPointForTouches,看来该函数的目的是创建触摸字典并缓存它们以进行快速查找。作为缓存,它看起来像是在程序的整个生命周期中保留其内存并且从不释放自身的缓存。那么要确定一下,这个泄漏是发生在程序运行期间还是程序退出之后?如果之后,那么我所描述的很可能并不是真正的泄漏。
I am purely guessing here, given that the function is named "cache"BeginPointForTouches, it would appear that the purpose of this function is to create a dictionary of touches and cache them for fast lookup. Being a cache, it looks like it is the kind that keeps its memory around throughout the lifetime of the program and never frees itself. So to make sure, does this leak happen during the program or after the program exits? If after, then what I described is likely and isn't really a leak.