ARC & Malloc: EXEC_BAD_ACCESS - PullRequest
       15

ARC & Malloc: EXEC_BAD_ACCESS

5 голосов
/ 03 февраля 2012

Я уже некоторое время работаю над проектом, и я решил сделать прыжок в ARC. Я наткнулся на какой-то код, который бомбил каждый раз, и я хотел бы знать, почему. Мне удалось упростить его до этого фрагмента:

typedef __strong id MYID;

int main(int argc, char *argv[])
{ 
    MYID *arr = (MYID *) malloc(sizeof(MYID) * 4);

    arr[0] = @"A";     // always get an EXEC_BAD ACCESS HERE
    arr[1] = @"Test";
    arr[2] = @"Array";
    arr[3] = @"For";

    // uh oh, we need more memory
    MYID *tmpArray = (MYID *) realloc(arr, sizeof(MYID) * 8);
    assert(tmpArray != NULL);

    arr = tmpArray;

    arr[4] = @"StackOverflow";  // in my actual project, the EXEC_BAD_ACCESS occurs here
    arr[5] = @"Is";
    arr[6] = @"This";
    arr[7] = @"Working?";

    for (int i = 0; i < 8; i++) {
        NSLog(@"%@", arr[i]);
    }

    return 0;
}

Я не совсем уверен, что здесь происходит, надоело это в 4 разных проектах, и все они терпят неудачу. Что-то не так с моим malloc звонком? Иногда он возвращает ноль, а иногда возвращает указатель, к которому у меня нет доступа.

Ответы [ 2 ]

13 голосов
/ 03 февраля 2012

Сбой в том, что вы преобразуете память malloc в массив объектов C.В тот момент, когда вы попытаетесь назначить один из слотов, ARC освободит предыдущее значение, которое будет мусорной памятью.Попробуйте использовать calloc() вместо malloc() для получения обнуленной памяти, и она должна работать.

Обратите внимание, что ваш вызов realloc() также не будет заполнять нулями любую новую выделенную память, поэтому если вам нужен1006 *, тогда вы можете захотеть использовать временный указатель void*, который затем заполняете нулями вручную, прежде чем присваивать массиву объектов.

8 голосов
/ 03 февраля 2012

Функция malloc не обнуляет память, которую она выделяет. Память может содержать случайный мусор.

Из руководства Clang Автоматический подсчет ссылок , раздел 4.2:

Для __strong объектов новый pointee сначала сохраняется; во-вторых, lvalue загружается примитивной семантикой; в-третьих, новый pointee сохраняется в lvalue с примитивной семантикой; и наконец, старый pointee освобожден .

Так что, вероятно, здесь происходит то, что malloc возвращает память, которая содержит случайные ненулевые значения. ARC пытается использовать это случайное значение в качестве указателя на объект и освобождать его, но это недопустимый указатель на объект. Краш.

...