【问题标题】:EXC_BAD_ACCESS when passing a pointer-to-pointer in a struct?在结构中传递指向指针时的 EXC_BAD_ACCESS?
【发布时间】:2012-04-04 09:02:17
【问题描述】:

我在一个结构中有一个 CGPoints 的 c 数组。添加另一个 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 &lt; origCount) ? *focal-&gt;focalPoints[i] : focalPoint;。那我到底做错了什么?

【问题讨论】:

  • 我不太确定,但我认为 newPoints[i] 是一个 CGPoint,而 *focal->focalPoints[i] 是一个 CGPoint 指针...
  • 您是否考虑过使用链表甚至NSMutableArray/NSValue,这样您就不会在每次想要添加点时都分配、复制和释放整个东西?跨度>
  • fPoints 的原始 malloc 在技术上没有被使用。但是我分配了空间,因为 AddFocalPoint 函数会对其调用 free ,并且我不想释放尚未 malloc 的空间。 &amp;fPoints 添加一个指向 fPoints 的额外指针。我这样做是因为我相信这是替换 c-arrays 的唯一方法。
  • "fPoints 的原始malloc() 没有在技术上使用":你不需要分配它,那么——只要你将它初始化为NULL,你'会好的。 free(NULL) 是一个完全安全的无操作。
  • 大声笑...哦,是的,我忘记了。谢谢,自从我弄乱了c指针以来已经有一点了。

标签: objective-c c arrays reference


【解决方案1】:

相信问题在于分配为&amp;fPointsGCPoint *fPoints 计算为该地址的地址...一旦函数退出,该地址将不再有效。

(它指向的数据被malloc很好地分配了。)

【讨论】:

  • 函数退出后结构体不被访问。我通过引用另一个函数来传递结构。当该函数返回时,我将结构中修改的数据传递给另一个函数(全部仍在创建该结构的函数中)。然后函数退出,结构被销毁。没有其他地方可以访问它。
  • 好吧,这就是我的想法。祝你好运:(
【解决方案2】:

这有点远,但*focal-&gt;focalPoints[i] 中的操作员优先级可能存在问题。您是否尝试根据您要达到的目的添加括号?

【讨论】:

  • 括号是什么意思?我会把它们放在哪里?
  • *focal-&gt;focalPoints[i],我不知道是*(focal-&gt;focalPoints[i])*(focal-&gt;focalPoints)[i](*focal)-&gt;focalPoints[i].. 我想你明白我在这里想说什么
  • 好吧,你知道什么。你是对的。我添加了一行CGPoint *focalPoints = *focal-&gt;focalPoints;,然后像这样访问它:newPoints[i] = (i &lt; origCount) ? focalPoints[i] : focalPoint;
【解决方案3】:

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

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

这几乎就是您正在做的事情,但是您可以让库为您处理它。

(我也可以谦虚地建议在你的函数中使用“焦点”这个词来命名变量吗?)(另外,我不太清楚为什么你的结构中的focalPoints 是一个指向指针的指针. 你只需要一个结构数组——单个指针就可以了。)

考虑以下(有点广泛的)重写;希望对您有所帮助。

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;
}

【讨论】:

  • 太好了,谢谢。很抱歉,我已经接受了另一个答案,但我确实对你的答案投了赞成票。首先,我不能使用 obj-c 对象,因为我使用的是 ARC,它不允许这样做,所以 NSMutableArray 被淘汰了。我不知道realloc 确实简化了事情,谢谢!我为我的 c 数组使用双指针的原因是我根本无法用新数组替换数组。无论我如何尝试,当我退出函数时,结构都会保留一个指向旧数组的指针。我在这里找到了答案:stackoverflow.com/questions/1106957/….
  • 很高兴它有帮助。不要担心接受;无论如何,我得到的无用代表比我知道的要多。即使使用 ARC,也应该有一种方法可以将对象放入结构中(我认为 __unsafe_unretained 可能就是您所需要的),但这可能不值得头疼。
  • 是的,这可能行得通,但我现在已经开始工作了,所以我不会搞砸它。此外,我喜欢回到一些 c。
猜你喜欢
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
  • 2019-03-30
  • 1970-01-01
  • 2018-04-15
相关资源
最近更新 更多