Realloc не копирует старые данные

Фон:

Я создал массив с помощью calloc(), и все отлично работало. Затем я использовал realloc(), чтобы увеличить массив. Кажется, он просто создает новый указатель, в котором ничего нет, и вызывает ошибку времени выполнения, когда я пытаюсь получить доступ к элементам в массиве.

Мой код:

#include <stdio.h>

int main() {

  int *arr;

  for (int i = 0; i < 5; i++){
      if (i == 0) {
          if ((arr = (int *) calloc(1, sizeof(int))) == NULL) {
              printf("NO MORE SPACE TERMINATING PROGRAM");

              return NULL;
          }

      } else {
          int *tmp;

          if ((tmp = (int *)realloc(arr, 4*sizeof(int)) == NULL)){
              printf("NO MORE SPACE TERMINATING PROGRAM");
          }

          arr = tmp;
      }

      arr[i] = i;
  }
}

Он выдает ошибку времени выполнения в строке arr[i]=i;, когда i = 1;

Когда я добавляю точку останова на 1 строку выше arr = temp;, это показывает, что temp полностью пуст.

Почему это происходит?

--------Обновлять----------------

Спасибо за помощь. Вот рабочий обновленный код:

#include <stdio.h>
#include <stdlib.h>

int main(){
    int *arr = NULL;

    for (int i = 0; i < 5; i++){
        int *tmp;

        if ((tmp = realloc(arr, (i+1) * sizeof(int))) == NULL){
            printf("NO MORE SPACE TERMINATING PROGRAM");
        }

        arr = tmp;

        arr[i] = i;
    }

    for (int i = 0; i < 5; i++) {
        printf("%i",arr[i]);
    }
}

Вывод: 01234

Спасибо всем за вашу помощь.


person Joel    schedule 16.11.2015    source источник
comment
Вы не #include <stdlib.h>, именно поэтому вам не следует приводить результат malloc, calloc или realloc. Также arr[4] — это один элемент за пределами 4, которые вы realloc (3 — это максимальный индекс, к которому вы можете обратиться с помощью массива из 4 элементов).   -  person Kninnug    schedule 16.11.2015
comment
Не имеет отношения к вашей проблеме, но случай i == 0 является избыточным, если вы изначально использовали int *arr = NULL;. Безопасно перераспределять нулевой указатель, и в этом случае он ведет себя так же, как malloc.   -  person M.M    schedule 16.11.2015
comment
Кроме того, из соображений стиля for (i = 0; ___; i++) { if (i == 0) {....} можно было бы написать более четко, просто указав блок {....} перед началом цикла.   -  person M.M    schedule 16.11.2015


Ответы (1)


Всегда прислушивайтесь к предупреждениям. Это покажет:

warning: assignment makes pointer from integer without a cast [enabled by default]
           if ((tmp = (int *)realloc(arr, 4*sizeof(int)) == NULL)){

Что говорит вам о том, что компилятор присваивает int tmp. Как это возможно? Если вы посмотрите внимательно, то обнаружите, что скобки неверны. Фактически он присваивает результат realloc(arr, 4*sizeof(int)) == NULL tmp. Правильный код ниже. Обратите внимание, где скобки вокруг присваивания.

if ((tmp = realloc(arr, 4*sizeof(int))) == NULL)

И вам не хватает #include <stdlib.h> для определений calloc и realloc.

Обновление: как было предложено М.М. и другими, даже если вышеперечисленное исправлено, realloc по-прежнему неверно, поскольку он выделяет только 4 элемента, тогда как цикл for будет получать доступ к 5 элементам. Так что нужно изменить 4 на 5 или i+1, например. И хотя это не вызывает никаких функциональных проблем, нет необходимости использовать realloc в каждом цикле после 0.

person kaylum    schedule 16.11.2015
comment
Также было бы неплохо упомянуть, что 4 недостаточно; возможно (i+1) было бы лучше - person M.M; 16.11.2015