Ошибка сегментации с использованием realloc на больших массивах в C

Я пытаюсь реализовать динамический массив - если массив заполнен, и вы добавите еще одну точку, он удвоит размер массива. Размер массива обозначается len, а пространство, оставшееся в массиве, обозначается зарезервированным. Если я добавляю 5650 точек, все работает нормально, но как только я набираю 5700 или более, возникает ошибка сегментации. Любые идеи относительно того, что может быть причиной этого?

int point_array_append( point_array_t* pa, point_t* p )
{
    if(pa->reserved==0)
    {
        if(!(realloc(pa->points, sizeof(point_t)*(pa->len * 2))))
            return 1;
        pa->reserved=pa->len;
    }
    pa->len++;
    pa->reserved--;
    pa->points[(pa->len)-1] = *p;
    return 0;
}

person user120920    schedule 23.11.2014    source источник
comment
Чему равно sizeof(point_t)?   -  person vines    schedule 24.11.2014


Ответы (2)


realloc изменит размер массива (если это возможно), а затем вернет указатель на новый адрес ваших данных. Если это не удастся, он вернет нулевой указатель, вы должны проверить это (что вы и сделали, что приятно видеть!). Кроме того, важно отметить, что realloc может переместить память в другое место, если это необходимо. В этом коде, если такое перемещение произойдет, у вас будут проблемы, потому что вы отслеживаете только то, где находится исходный указатель на данные. Поэтому, если бы realloc переместил данные куда-то еще, вы бы писали туда, куда не должны были бы, что является неопределенным поведением, и это может вызвать ошибку сегментации, которую вы видите. Скорее всего, до 5650 пунктов realloc не совершал никаких перемещений, но больше, чем это количество, вызывало переход к другому указателю.

Исправление заключается в использовании указателя, возвращаемого realloc, и убедитесь, что этот указатель не равен нулю, прежде чем что-либо с ним делать.

person shuttle87    schedule 23.11.2014
comment
Я знаю, что не должен писать спасибо согласно правилам, но я не могу устоять - спасибо! Это объяснение было очень ясным - я действительно оценил объяснение причин, по которым оно терпит неудачу, и как его правильно реализовать. - person user120920; 24.11.2014

realloc возвращает указатель на новую память. Вы не можете просто так выбросить это.

person MTilsted    schedule 23.11.2014
comment
Связано: И это может привести к сбою, и в этом случае вы все еще несете ответственность за переданный указатель. - person Deduplicator; 24.11.2014
comment
Не могли бы вы немного уточнить? Я думал, что способ, которым я использовал realloc, увеличит размер pa-points на 100%, а затем, если это не удастся, я верну 1. - person user120920; 24.11.2014
comment
Realloc обычно не изменяет существующий массив. Он выделяет новый массив, копирует существующий массив в новый массив и возвращает указатель на новый массив. Вы должны установить pa->points в возвращаемое значение realloc. - person JS1; 24.11.2014