我是C的新手,我正在开展一个项目,我一直在努力工作几天,我无法弄清楚问题出在哪里。
基本上,应用程序应该做的是从数据库读取数据并将值插入到结构中。有些行与每个行相关,因此在结构中是一个链表,它将包含数据库中的其他值。
我不知道我将从数据库中获取多少条记录,因此我最初将结构malloc为100项,并且我跟踪索引,如果它达到100,则将结构重新分配给再添加100个项目。重新分配位似乎工作,但这就是为什么我尝试在结构中插入一些东西,我得到一个段错误。
以下是主要结构的定义。
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链表进行malloc
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运行我的程序,但我不完全确定所有消息的意思和做谷歌,虽然我找到了一些东西,但没有帮助我理解这个问题。
来自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
Line performreport.c:3112是
if (dataRow > -1 && callLogSearchData[dataRow].outboundLegs == NULL)
performreport.c:3123的行是
outboundCallLegStartPtr = callLogSearchData[dataRow].outboundLegs;
performreport.c: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 :(得分:0)
我可以看到一个潜在的问题:
在insertOutboundLegToList
中,您似乎采用第一个条件来表示&#34;有一个已分配的结构,但它是空的,但尚未被填充&#34;。然后填写,但忘记了NULL
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;
此外,realloc函数中的这一行
Temp
可能缺少{{1}}。