在大循环期间溢出堆栈:我该如何解决这个问题?

时间:2011-10-30 16:54:55

标签: objective-c ios xcode cocoa-touch stack-overflow

考虑以下图片:

enter image description here

我的应用程序首先找到所有蓝色像素,并记录所有兄弟姐妹的x,y坐标(给定像素的兄弟姐妹是那些边界的兄弟姐妹:上,下,左,右,左上,上 - 对等等)。然后它遍历所有这些蓝色像素,以便弄清楚他们有多少蓝色兄弟。目标是最终确定哪一组蓝色像素是最大的。

这是一个很大的循环,它最终导致错误“警告:无法恢复以前选择的帧”。我相信这是因为我在堆栈中溢出。如果是这种情况,您会如何建议我更改我的代码以解决此问题?

以下是代码:

开始循环的方法:

for (NSString *key in pixelItemDict) {
    Pixel *px = [pixelItemDict objectForKey:key];
    if (!px.hasBeenCounted) {

        //If it hasn't been counted, we know that we're onto a new distinct area, because otherwise counterForSiblingsOfPixel would have already counted it. So we now add a copy of the pixelsCurrentlyBeingCounted array, empty that array, and reset the counter
        [pixelCounterDict setObject:[pixelsCurrentlyBeingCounted copy] forKey:[NSString stringWithFormat:@"%i",currentPxCounter]];

        [pixelsCurrentlyBeingCounted removeAllObjects];

        [self counterForSiblingsOfPixel:px];

    }
}

连续调用自身的方法,导致堆栈溢出:

- (void)counterForSiblingsOfPixel:(Pixel *)px
{
    [pixelsCurrentlyBeingCounted addObject:px];
    currentPxCounter++;
    px.hasBeenCounted = true;

    for (Pixel *sibling in px.siblings) {
        if (!sibling.hasBeenCounted) [self counterForSiblingsOfPixel:px];
    }
}

基本上,我有一个包含所有蓝色像素的pixelItemDict。我枚举这个字典,在每个字典上调用方法counterForSiblingsOfPixel:。该方法依次调用传递给它的像素的每个兄弟姐妹。 forin循环仅在蓝色区域中的每个像素都被计数后才重新获得控制权。因此,大面积的蓝色会导致counterForSiblingsOfPixel:调用自身很多次,导致溢出。

在这种情况下是否应该使用标准设计模式?

1 个答案:

答案 0 :(得分:4)

首先,您不是要修改px,因此每次调用-counterForSiblingsOfPixel:都会做同样的事情。当您使用递归时,您希望确保每个递归级别在某种程度上简化了问题。如果递归最终没有达到某种基本情况,它将永远继续下去,是的,溢出堆栈。因此,首先要确保您对该方法的调用是针对某些更简单的情况。

其次,您可能不希望仅通过一个像素进行简化...如果此方法将像素分成两半并且每半次递归调用自身,那就没问题了,因为您最终只会log2(像素)递归级别 - 大约20个百万像素。但是如果你处理一个像素然后递归调用剩下的像素,你最终会得到1000000级递归,这也会溢出。