Я новичок в 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, ×StructHasBeenReallocated, 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";
}
}
К сожалению, для всего кода, но Я не знаю точно, где может быть проблема. Глядя в дамп ядра, похоже, что что-то мешает памяти, когда я проверяю некоторые из значений внутри структур, это просто искаженный беспорядок.
Спасибо за любую помощь, которую вы можете предоставить.
Это означает, что вы читаете неинициализированную переменную at performreport.c: 3480. Если вы читаете указатель, а затем получаете доступ к данным через этот указатель, вы теряете. Я не могу сказать, где эта линия, на основе фрагмента. Только вы можете нам рассказать. Но попробуйте прочитать выход valgrind, это действительно не так сложно. – dan3
Извините, со всеми изменениями, которые я сделал, я взял что-то по ошибке, поэтому он не инициализировал его. Проблема заключается в том, что после выполнения realloc в структурах, когда он «outboundCallLegStartPtr-> nextLeg = NULL'' после того, как он был перераспределен, он выходит из строя, и если я пытаюсь его распечатать, он говорит об этом за пределами, поэтому что-то в realloc закручивает память, но я не вижу, что – Boardy
Не могли бы вы четко отметить строку 'performreport.c: 3480' в функции' insertOutboundLegToList', пожалуйста? – us2012