2014-10-06 4 views
1

На RHEL6 у меня возникла странная проблема с realloc(). В какой-то момент в программе realloc() возвращает NULL (старый указатель имеет адрес и имеется доступная память). То, что выделяется, составляет 200 структурных элементов (структура ниже). По какой-то причине, когда я делаю realloc(), это работает, но я должен назначить старый указатель на новый. Ниже приведена упрощенная версия моего кода.Почему realloc() не работает, когда malloc() успешно работает в C?

Возможно, это проблема настройки сервера, а не программирующая. Каково твое мнение?
Спасибо.

//hearder file 
typedef struct {  /* Variable Node Detail Record */ 
    long  next; 
    long  mask; 
    char  *value; 
    // more stuff... 
} NODETEST; 

extern NODETEST *oldNodes; 
extern NODETEST *newNodes; 

//program 
#define MAXSIZE 200 

// do some stuff with oldNodes.... 

int alloc_nodes (void) 
{ 
    // Allocate or grow the table 
    oldNodes = (NODETEST *) malloc(MAXSIZE * sizeof(NODETEST)); 
    if(oldNodes == NULL) { 
      //handle exception... 
      exit(1); 
     } 

    //oldNodes = (NODETEST *) realloc(oldNodes,MAXSIZE * sizeof(NODETEST)); // *** FAILS 

    newNodes = (NODETEST *) realloc(oldNodes,MAXSIZE * sizeof(NODETEST)); // *** WORKS 

    if(newNodes == NULL){ 
     printf("errno=%d\n", errno); 
    }else{ 
     oldNodes = newNodes;   } 
} 
+5

Использовать 'perror', когда' realloc' или 'malloc' (или' calloc') терпят неудачу. –

+1

использовать 'perror' и показать нам, что он возвращает –

+0

Работает ли' free' на старом указателе? – Marian

ответ

1

Вашего первый вызов malloc с размером S, а затем realloc с таким же размером S. Это неправильно: вы должны пройти realloc новый разыскиваемого размер (независимо от текущего размера - это не приращение). Здесь есть большой шанс. realloc возвращает точно тот же указатель, который он получил. Кстати, непонятно, почему вы хотите сделать с malloc, а затем realloc. Дает нам более подробную информацию.

Если вы хотите динамическую таблицу, размер которой автоматически меняет, необходимо выделить начальный размер хранения ее размер в переменной (например, alloc_size) и сохранить текущее число занятых элементов в другой переменной (например, n_elem). Когда вы добавляете элемент, вы увеличиваете это число. Когда таблица полна, перераспределите ее. Вот набросок

NODETEST *newNodes = NULL; 
int allocated_elem = 0; 
int n_elem = 0; 

#define ALLOC_INCR 200 

затем при каждом добавлении:

if (n_elem >= alloc_size) { // the first time realloc is as malloc since nodes == NULL 
    alloc_size += ALLOC_INCR; 
    nodes = (NODETEST *) realloc(nodes, alloc_size * sizeof(NODETEST)); 
    if (nodes == NULL) { 
     //handle exception... 
     exit(1); 
    } 
} 
// add your element at nodes[n_elem] 
n_elem++; 

Напомним, что перераспределить действует как таНос, когда принятый указатель NULL (в случае первого вызова). Таким образом, он выделяет исходную таблицу. Последующие вызовы перераспределяют его, регулируя размер с постоянным приращением (здесь 200). Некоторые другие схемы возможны для расширения таблицы, например, вы можете умножить размер на коэффициент (например, 2), начиная с 32:

if (n_elem >= alloc_size) { // the first time realloc is as malloc since nodes == NULL 
    alloc_size = (alloc_size == 0) ? 32 : alloc_size * 2; 

Regarind в FAIL и WORKS комментарии: совершенно ясно, что если вы присвойте oldNodes (в коде FAIL), тогда newNodes не назначен и сохраняет свое начальное значение, которое равно нулю (NULL), поскольку оно объявлено как глобальная переменная и не инициализировано (ну, я полагаю, здесь extern). Таким образом, тест if (newNodes == NULL), вероятно, не удастся.

+0

ваш код настолько близок к оригиналу, который у меня есть. Фактически, в моем коде realloc() использует другой размер, чем указывает текущий указатель. Я должен был сделать мой пример лучше, извините, я просто не могу опубликовать оригинальный код. Я буду работать над своими примерами в будущем, так много таких советов на этой доске, как вы. Еще раз спасибо. – user3772839