EXC_BAD_ACCESS при передаче указателя на указатель в структуре? - PullRequest
1 голос
/ 20 марта 2012

У меня есть c-массив CGPoints в структуре. Мне нужно заменить этот массив при добавлении другого 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;
}

Ошибка EXC_BAD_ACCESS возникает в приведенном выше коде в строке 8: newPoints[i] = (i < origCount) ? *focal->focalPoints[i] : focalPoint;. Так что именно я делаю не так?

Ответы [ 3 ]

3 голосов
/ 20 марта 2012

Это довольно далеко, но, возможно, есть проблема с приоритетом оператора в *focal->focalPoints[i].Вы пытаетесь добавить скобки в соответствии с тем, что вы пытаетесь достичь?

2 голосов
/ 20 марта 2012

I полагаю, проблема возникает, когда GCPoint *fPoints, выделенный как &fPoints, вычисляет адрес этого ..., который больше не действителен после выхода из функции.

(Данные, которым он указывает , были распределены в порядке с malloc.)

1 голос
/ 20 марта 2012

Помимо предложения, которое я сделал в комментарии об использовании связанного списка / NSMutableArray, мое другое предложение будет состоять в том, чтобы вы использовали realloc() вместо постоянного использования malloc(), копирование вручную, а затем free() использование старого выделения.

void * realloc(void *ptr, size_t size);
Функция realloc() пытается изменить размер выделения, на который указывает ptr, на sizeи возвращает ptr.Если недостаточно места для увеличения выделения памяти, на которое указывает ptr, realloc() создает новое распределение, копирует столько старых данных, на которые указывает ptr, сколько будет соответствовать новому выделению, освобождает староеВыделение и возвращает указатель на выделенную память.

Это в значительной степени именно то, что вы делаете, но вы можете позволить библиотеке справиться с этим за вас.

(Могу ли я также смиренно предложить немного меньше использовать слово «focal» для именования переменных в вашей функции?) (Кроме того, я не совсем понимаю, почему focalPoints в вашей структуре является указателем -to-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;
}
...