2013-09-13 1 views
0

Я новичок в C, и я работаю над проектом, с которым я боролся, пытаясь работать в течение нескольких дней, и я не могу понять, где проблема.Segfault с структурой перераспределения памяти и связанным списком

В принципе, то, что должно выполнять приложение, это считывать данные из базы данных и вставлять значения в структуру. Некоторые строки связаны с каждой из них, поэтому внутри структуры есть связанный список, который будет содержать другие значения из базы данных.

Я не знаю, сколько записей я собираюсь выбраться из базы данных, поэтому изначально malloc структуры должен быть 100 элементов, и я отслеживаю индекс, который, если он достигает 100, затем перерабатывает структуры добавить еще 100 предметов. Бит перераспределения, похоже, работает, но именно поэтому я пытаюсь вставить что-то в связанный список внутри структуры, в которой я получаю segfault.

Ниже приведено определение основной структуры.

typedef struct CallLogSearchDataStruct 
{ 
    char * date; 
    char * time; 
    char * bParty; 
    char * aParty; 
    float duration; 
    char * cleardownCause; 
    struct CallLogSearchOutboundStruct * outboundLegs; 
} callLogSearchDataStruct; 

Ниже приведен код для связанного списка (CallLogSearchOutboundStruct)

typedef struct CallLogSearchOutboundStruct 
{ 
    char * target; 
    float duration; 
    char * cleardownCause; 
    struct CallLogSearchOutboundStruct * nextLeg; 
} callLogSearchOutboundStruct; 

Я инициализирует структуры, используя следующий код

callLogSearchData = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchDataStruct)); 
callLogSearch = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchResultStruct)); 
switches = calloc(INITIAL_CALL_STRUCT_SIZE, sizeof(switchIDStructure)); 

Каждый раз, когда он петлями вокруг данных, я таНос связанный с OutboundLeg список в структуре с использованием следующего кода

if (dataRow > -1 && callLogSearchData[dataRow].outboundLegs == NULL) 
       { 
        //Initialise the outbound struct 
        callLogSearchData[dataRow].outboundLegs = malloc(sizeof(callLogSearchOutboundStruct)); 
        callLogSearchData[dataRow].outboundLegs->cleardownCause = NULL; 
        callLogSearchData[dataRow].outboundLegs->duration = 0; 
        callLogSearchData[dataRow].outboundLegs->target = NULL; 
        callLogSearchData[dataRow].outboundLegs->nextLeg = NULL; 
       } 
      outboundCallLegStartPtr = callLogSearchData[dataRow].outboundLegs; 
      outboundCallLegStartPtr->nextLeg = NULL; 

Ниже приведен код, который вызывает функцию для вставки данных в связанный список в структуре

insertOutboundLegToList(outboundCallLegStartPtr, targetBuffer, durationBuffer, atoi(rowReport[cleardownColIndex]), debugFile); 

Ниже приведен код для фактической функции вставки

void insertOutboundLegToList(callLogSearchOutboundStruct * outboundLeg, char * target, float duration, int cleardown, FILE * debugFile) 
{ 
    //fprintf(debugFile, "INSIDE INSERT OUTBOUND LEG FUNCTION\n"); 
    if (outboundLeg->target == NULL) 
    { 
     outboundLeg->target = strdup(target); 
     outboundLeg->duration = duration; 
     outboundLeg->cleardownCause = strdup(setCallResult(cleardown)); 
     //fprintf(debugFile, "Outbound target is: %s\n", outboundLeg->target); 
    } 
    else 
    { 
     while (outboundLeg->nextLeg != NULL) 
     { 
      outboundLeg = outboundLeg->nextLeg; 
     } 
     outboundLeg->nextLeg = (callLogSearchOutboundStruct*)malloc(sizeof(callLogSearchOutboundStruct)); 
     outboundLeg = outboundLeg->nextLeg; 
     outboundLeg->target = strdup(target); 
     outboundLeg->duration = duration; 
     outboundLeg->cleardownCause = strdup(setCallResult(cleardown)); 
     //fprintf(debugFile, "Outbound target is: %s\n", outboundLeg->target); 
     outboundLeg->nextLeg = NULL; 
    } 


} 

Ниже, как я вызовите функцию, чтобы проверить, необходимо ли перераспределять структуры

if (reallocateStructures(&callLogSearch, &callLogSearchData, &switches, &timesStructHasBeenReallocated, currentStructIndexValue, dataRow) == 0) 
        { 
         //Structures have been reallocated so reset the index 
         currentStructIndexValue = -1; 
        } 

И ниже фактическая функция перераспределения структур

int reallocateStructures(callLogSearchResultStruct **callLogSearch, callLogSearchDataStruct ** callLogSearchData, 
     switchIDStructure ** switches, int *timesStructHasBeenReallocated, int currentStructIndexValue, 
     int dataRow) 
{ 
    int INITIAL_CALL_STRUCT_SIZE = 100; 
    int currentSize = 0; 
    int newSize = 0; 
    int initFromIndex = 0; 
    callLogSearchResultStruct * callLogSearchTemp; 
    callLogSearchDataStruct * callLogSearchDataTemp; 
    switchIDStructure * switchesTemp; 


    printf("Current Struct Index Value: %i\n", currentStructIndexValue); 

    if (currentStructIndexValue >= INITIAL_CALL_STRUCT_SIZE) { 
     printf("REALLOCATING STRUCTURES"); 
     currentSize = currentStructIndexValue * *timesStructHasBeenReallocated; 

     newSize = currentSize + INITIAL_CALL_STRUCT_SIZE; 
     *timesStructHasBeenReallocated = *timesStructHasBeenReallocated + 1; 


     callLogSearchTemp = (callLogSearchResultStruct*)realloc(*callLogSearch, (newSize * sizeof(callLogSearchResultStruct))); 
     callLogSearchDataTemp = (callLogSearchDataStruct*)realloc(*callLogSearchData, (newSize * sizeof(callLogSearchDataStruct))); 
     switchesTemp = (switchIDStructure*)realloc(*switches, (newSize * sizeof(switchIDStructure))); 


     /**callLogSearchData = realloc(*callLogSearchData, newSize * sizeof (callLogSearchDataStruct)); 
     *callLogSearch = realloc(*callLogSearch, newSize * sizeof (callLogSearchResultStruct)); 
     *switches = realloc(*switches, newSize * sizeof (switchIDStructure)); 
     */ 
     for (initFromIndex = currentSize; initFromIndex < newSize; initFromIndex++) { 
      callLogSearchDataTemp[initFromIndex].aParty = NULL; 
      callLogSearchDataTemp[initFromIndex].bParty = NULL; 
      callLogSearchDataTemp[initFromIndex].cleardownCause = NULL; 
      callLogSearchDataTemp[initFromIndex].date = NULL; 
      callLogSearchDataTemp[initFromIndex].duration = 0; 
      callLogSearchDataTemp[initFromIndex].outboundLegs = NULL; 
      callLogSearchDataTemp[initFromIndex].time = NULL; 

      callLogSearchTemp[initFromIndex].date = NULL; 
      callLogSearchTemp[initFromIndex].dRowIndex = dataRow; 

      switchesTemp[initFromIndex].switchID = NULL; 
     } 

     *callLogSearch = callLogSearchTemp; 
     *callLogSearchData = callLogSearchDataTemp; 
     *switches = switchesTemp; 
     return 0; 
    } 
    else 
    { 
     return 1; 
    } 
} 

Я попытался запустить свою программу через Valgrind, но я не совсем уверен, что означает, что все сообщения и делает Google, хотя я нашел что-то, не помогли мне понять проблему.

Сообщения из Valgrind являются

==9152== Invalid read of size 4 
==9152== at 0x80544EB: GenerateCallLog (performreport.c:3112) 
==9152== by 0x804AA49: ProcessReport (performreport.c:344) 
==9152== by 0x8056C7E: PerformReportCheck (reportcheck.c:72) 
==9152== by 0x80494D0: main (main.c:82) 
==9152== Address 0x47b22b0 is not stack'd, malloc'd or (recently) free'd 
==9152== 
==9152== Invalid read of size 4 
==9152== at 0x80545CF: GenerateCallLog (performreport.c:3123) 
==9152== by 0x804AA49: ProcessReport (performreport.c:344) 
==9152== by 0x8056C7E: PerformReportCheck (reportcheck.c:72) 
==9152== by 0x80494D0: main (main.c:82) 
==9152== Address 0x47b22b0 is not stack'd, malloc'd or (recently) free'd 
==9152== 
==9152== Invalid write of size 4 
==9152== at 0x80545DF: GenerateCallLog (performreport.c:3124) 
==9152== by 0x804AA49: ProcessReport (performreport.c:344) 
==9152== by 0x8056C7E: PerformReportCheck (reportcheck.c:72) 
==9152== by 0x80494D0: main (main.c:82) 
==9152== Address 0x35c is not stack'd, malloc'd or (recently) free'd 

Линия performreport.c: 3112 является if (dataRow > -1 && callLogSearchData[dataRow].outboundLegs == NULL)

Линия performreport.c: 3123 является outboundCallLegStartPtr = callLogSearchData[dataRow].outboundLegs;

Линия performreport.с: 3124 является outboundCallLegStartPtr->nextLeg = NULL;, это его линия, которая также вызывает дамп ядра после перераспределениях произошли

Функция setCallResult по требованию заключается в следующем:

char * setCallResult(int callResult) 
{ 
    if (callResult == 1) 
    { 
     return "Answered"; 
    } 
    else if (callResult != 3) 
    { 
     return "Unanswered"; 
    } 
    else if (callResult == 3) 
    { 
     return "Engaged"; 
    } 
    else 
    { 
     return "N/A"; 
    } 
} 

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

Спасибо за любую помощь, которую вы можете предоставить.

+0

Это означает, что вы читаете неинициализированную переменную at performreport.c: 3480. Если вы читаете указатель, а затем получаете доступ к данным через этот указатель, вы теряете. Я не могу сказать, где эта линия, на основе фрагмента. Только вы можете нам рассказать. Но попробуйте прочитать выход valgrind, это действительно не так сложно. – dan3

+0

Извините, со всеми изменениями, которые я сделал, я взял что-то по ошибке, поэтому он не инициализировал его. Проблема заключается в том, что после выполнения realloc в структурах, когда он «outboundCallLegStartPtr-> nextLeg = NULL'' после того, как он был перераспределен, он выходит из строя, и если я пытаюсь его распечатать, он говорит об этом за пределами, поэтому что-то в realloc закручивает память, но я не вижу, что – Boardy

+0

Не могли бы вы четко отметить строку 'performreport.c: 3480' в функции' insertOutboundLegToList', пожалуйста? – us2012

ответ

0

Там одна потенциальная проблема я вижу:

В insertOutboundLegToList, вы, кажется, принять первое условие означает «есть выделенная структура, но она пуста, и все же должны быть заполнены». Затем вы заполните его, но вы забудете NULL ing nextLeg. Предположим, что nextLeg - это 0x75732d42, потому что это данные все еще там; следующий раз, когда функция вызывается, то вызвать else состояние:

while (outboundLeg->nextLeg != NULL) 
     { 
      outboundLeg = outboundLeg->nextLeg; 
     } 

Теперь nextLeg не является NULL, хотя это должно быть. После одной итерации outboundLeg указывает на 0x75732d42, хотя там нет выделенной структуры. На следующей итерации вы потерпите крах, потому что пытаетесь прочитать из недопустимого адреса памяти.


То, что я предлагаю, это (в insertOutboundLegToList):

if (outboundLeg->target == NULL) 
{ 
    outboundLeg->target = strdup(target); 
    outboundLeg->duration = duration; 
    outboundLeg->cleardownCause = strdup(setCallResult(cleardown)); 
    // HERE v HERE v HERE v HERE 
    outboundLeg->nextLeg = NULL; 
    ... 
} 

Кроме того, эта строка в функции перераспределить

*callLogSearchData = callLogSearchData; 

, вероятно, отсутствует Temp.

+0

, Я не совсем понимаю, что вы имеете в виду. Где я должен быть '' NULL'' outboundLeg-> nextLeg – Boardy

+0

@Boardy отредактирован, чтобы сделать это ясно – us2012

+0

Ах да это имеет смысл. Я сделал, что все еще получил исходную проблему, хотя – Boardy