2012-04-25 2 views
0

Я пытаюсь выделить некоторую память с помощью realloc(). Это работает до сих пор. Но если я хочу, чтобы назначить выделенную память на указатель в переменной структуры, я получаю ошибку сегментации:Ошибка сегментации после realloc(). Не удается назначить выделенную память указателю

// in header 
typedef struct { 
    int a; 
    char test[20]; 
} MyContent; 

typedef struct { 
    MyContent* values; 
    // simmilar to: MyContent values[] 
    // ... some other stuff 
} MyData; 

// in source 
void myFunction(MyData* dataPtr) { 
    dataPtr->values = NULL; 
    MyData* tempPtr = NULL; 

    for (int i = 1; i < 10; i++) { 
     tempPtr = (MyContent*) realloc(dataPtr->values, i * sizeof(MyContent)); 
     if (tempPtr == NULL) { 
      free(dataPtr->values); 
      break; 
     } 
     dataPtr->values = tempPtr; // Here I get the segmentation fault 
     dataPtr->values[(i-1)].a = 42; 
     // ... 
    } 
} 

Я не могу понять, что происходит не так здесь. Какие-либо предложения? Спасибо за вашу помощь.

+2

Ошибка в коде, который вы не ввели. В приведенном выше коде есть только одна существенная проблема - он неправильно описывает случай, когда 'realloc' возвращает' NULL'. Если вы можете опубликовать полный, компилируемый пример, который показывает ошибку, мы, возможно, найдем его для вас. В противном случае запустите 'valgrind' в вашем коде. (Кстати, это код C или код на C++? Вы помещаете оба тега, и это делает его очень запутанным.) –

+0

@DavidSchwartz, код OP, который будет опубликован, будет скомпилирован и запущен под C или C++ просто отлично :) – bdonlan

+0

@ bdonlan: Правильно, так что это невозможно понять, о чем он спрашивает. Если бы я собирался протестировать его, например, должен ли я проверить его как код C или код на C++? Если я собираюсь предложить исправления/изменения, должны ли они быть C или C++-кодом? –

ответ

1

Похоже, вы редактировали код. Редактированный код работает отлично.

#include<stdio.h> 
#include<malloc.h> 
#include<string.h> 
// in header 
typedef struct { 
    int a; 
    char test[20]; 
} MyContent; 

typedef struct { 
    MyContent* values; 
    // simmilar to: MyContent values[] 
    // ... some other stuff 
} MyData; 

// in source 
void myFunction(MyData* dataPtr) { 
    dataPtr->values = NULL; 
    MyData* tempPtr; 

    for (int i = 1; i < 10; i++) { 
     tempPtr = (MyData*) realloc(dataPtr->values, i * sizeof(MyContent)); 
     if (tempPtr == NULL) { 
      if(dataPtr->values) 
       free(dataPtr->values); 
      printf("realloc() failed\n"); 
      return ; 
     } 
     dataPtr->values = (MyContent*)tempPtr; // Here I get the segmentation fault 
     dataPtr->values[(i-1)].a = 42+i; 
     strcpy(dataPtr->values[(i-1)].test,"name"); 
    } 
} 

void PrintData(MyData* dataPtr) { 
    for (int i = 1; i < 10; i++) 
     printf("We have %s at %d\n",dataPtr->values[(i-1)].test,dataPtr->values[(i-1)].a); 
} 

main() { 
    MyData Sample; 
    myFunction(&Sample); 
    PrintData(&Sample); 
} 
+1

Извините, за изменения в коде на все ваши ответы. Я попытался снять все, что было необходимо для выяснения проблемы. Сделав это, я мог бы оставить или изменить что-то не так. Я понял, что аргумент, который я передал 'myFunction()', был errouneos, что я теперь понял из-за вашего примера здесь. Спасибо всем - отличная и быстрая поддержка. – fondor

0

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

if (tempPtr == NULL) { 
    // handle error condition or continue with original 'dataPtr->values' 
} 
else { 
    dataPtr->values = tempPtr; 
} 

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

+1

Это неверно. Вы не должны освобождать старый указатель, если он изменился; realloc уже позаботился об этом для вас. – bdonlan

+0

Функция 'reallocate' освободит сам старый блок. Вы не можете освободить его. –

+0

@bdonlan, David, извините, пропустил это ... спасибо – iammilind

0

На первый взгляд я не вижу проблемы, которая может привести к сбою в работе - адресация на основе данных немного нечетна, но не является неправильной. В коде может быть проблема, которую вы не показываете, что приводит к повреждению кучи или стека, которое вызывает вызов realloc. Или, если вы компилируете с оптимизацией, ваш отладчик может быть смущен тем, где происходит авария. Вы также вводите в заблуждение MyData и MyContent, но я предполагаю, что это только потому, что вы сделали ошибку при редактировании кода.

Заметим также, что если realloc сломается, вы аварии на линии после на который Вы указывали, как вы будете писать на пустой указатель. Вам нужно прервать, если tempPtr is NULL, а не просто удалить старый указатель. Опять же, это вызывает ошибку на другой строке, чем вы указали.

Я бы рекомендовал запустить вашу программу под valgrind, чтобы увидеть, где она сообщает об ошибках. Первой такой ошибкой может стать преступник.

+0

Да, я смутил MyData и MyContent в инструкции realloc(). Извините за это, я исправил его. Я также оставил «break», что вызвало дополнительную путаницу. – fondor

Смежные вопросы