在结构中传递指针指针时EXC_BAD_ACCESS?

时间:2012-03-19 20:39:46

标签: objective-c c arrays reference

我在一个struct中有一个C-array的C-array。我需要在添加另一个CGPoint时替换此数组。我发誓我正在做这件事,似乎工作很好几次,但最终我会得到一个EXC_BAD_ACCESS。我错过了什么?

这是结构,我已经截断它以删除许多不属于的项目。

typedef struct{
    CGPoint **focalPoints;
    NSUInteger focalPointCount;
    CGRect boundingRect;
}FocalPoints;

以下是我如何初始化它:

CGPoint *fPoints = (CGPoint *)malloc(sizeof(CGPoint));
FocalPoints focalInfo = {&fPoints, 0, rect};

请注意focalInfo通过引用传递给另一个函数,如:anotherFunction(&focalInfo)

现在这里是用新数组替换Points数组的函数:

void AddFocalPoint (CGPoint focalPoint, FocalPoints *focal){
    if (focalPoint.x == CGFLOAT_MAX) return;
    if (!CGRectContainsPoint(focal->boundingRect, focalPoint)) return;
    int origCount = focal->focalPointCount;
    int newCount = origCount + 1;
    CGPoint *newPoints = (CGPoint *) malloc((newCount) * sizeof(CGPoint));
    for (int i = 0; i < newCount; i++)
        newPoints[i] = (i < origCount) ? *focal->focalPoints[i] : focalPoint; //error occurs here
    free(*focal->focalPoints);
    *focal->focalPoints = newPoints;
    focal->focalPointCount = newCount;
}

第8行上面的代码中出现了EXC_BAD_ACCESS错误:newPoints[i] = (i < origCount) ? *focal->focalPoints[i] : focalPoint;。那究竟是我做错了什么?

3 个答案:

答案 0 :(得分:3)

这有点远,但可能在*focal->focalPoints[i]中存在运营商优先权问题。您是否尝试根据您要实现的目标添加括号?

答案 1 :(得分:2)

相信问题来自于GCPoint *fPoints分配为&fPoints的地址评估为该地址...一旦该函数退出就不再有效。

指向的数据已被malloc分配。)

答案 2 :(得分:1)

除了我在评论中提出的使用链接列表/ NSMutableArray的建议外,我的另一个建议是您使用realloc()而不是经常使用malloc(),复制方式手,然后free()旧的分配。

  

void * realloc(void *ptr, size_t size);
  realloc()函数尝试将ptr指向的分配大小更改为size,并返回ptr。如果没有足够的空间来扩大ptr指向的内存分配,realloc()会创建一个新的分配,复制尽可能多的ptr所指向的旧数据。新分配,释放旧分配,并返回指向已分配内存的指针。

这正是您正在做的事情,但您可以让图书馆为您处理。

(我还谦卑地建议在你的函数中使用“focal”这个词来命名变量吗?)(另外,我也不清楚为什么你的struct中的focalPoints是一个指针-pointer。你只需要一个结构数组 - 一个指针就可以了。)

考虑以下(稍微广泛)重写;希望它在某种程度上有所帮助。

typedef struct{
    CGPoint *points;    // Single pointer
    NSUInteger count;
    CGRect boundingRect;
} FocalPoints;

// Renamed to match Apple's style, like e.g. CGRectIntersectsRect()
void FocalPointsAddPoint (FocalPoints *, CGPoint);

void FocalPointsAddPoint (FocalPoints *f, CGPoint thePoint){
    if (thePoint.x == CGFLOAT_MAX) return;
    if (!CGRectContainsPoint(f->boundingRect, thePoint)) return;
    NSUInteger origCount = f->count;    // |count| is typed as NSUInteger; |origCount|
    NSUInteger newCount = origCount + 1;    // and |newCount| should be consistent
    // Greatly simplified by using realloc()
    f->points = (CGPoint *) realloc(f->points, newCount * sizeof(CGPoint));
    (f->points)[newCount-1] = thePoint;
    f->count = newCount;
}

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        // Just for testing; any point should be inside this rect
        CGRect maxRect = CGRectMake(0, 0, CGFLOAT_MAX, CGFLOAT_MAX);
        // Can initialize |points| to NULL; both realloc() and free() know what to do
        FocalPoints fp = (FocalPoints){NULL, 0, maxRect};
        int i;
        for( i = 0; i < 10; i++ ){
            FocalPointsAddPoint(&fp, CGPointMake(arc4random() % 100, arc4random() % 100));
            NSLog(@"%@", NSStringFromPoint(fp.points[i]));
        }

    }
    return 0;
}