我是C新手,但我目前正在开发一个C程序,我遇到了与结构和内存分配有关的问题。
我的代码中有一个永久的while循环,它会在满足某个条件时突破。在这个while循环中,它检查数据库并有一个while循环来循环MySQL行。
当程序首次加载时,它会创建3个结构,其中一个结构也包含一个链表,并初始化为100的大小。
当我的程序循环遍历MySQL行时,它会检查是否添加了100条记录,如果是,则执行realloc以将大小再增加100行。当我循环遍历所有MySQL行时,它返回到main while循环(永不停止的循环)和NULL的结构,然后再次将它们初始化为100行并重新开始。
我遇到的问题是,一旦它完成了所有mysql行的第一个完整循环并返回到主要的永不停止循环,并且结构被重新初始化为大小为100,在第17行我的程序段错误。当我检查GDB中的所有内容时,索引17处的结构会出现,表示结构中的某些元素超出范围。
以下是我遇到问题的结构的定义。
typedef struct CallLogSearchDataStruct
{
char * date;
char * time;
char * bParty;
char * aParty;
float duration;
char * cleardownCause;
struct CallLogSearchOutboundStruct * outboundLegs;
} callLogSearchDataStruct;
以下是程序首次运行时最初设置的结构
callLogSearchData = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchDataStruct));
callLogSearch = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchResultStruct));
switches = calloc(INITIAL_CALL_STRUCT_SIZE, sizeof(switchIDStructure));
INITIAL_CALL_STRUCT_SIZE
等于100
。
以下是调用reallocateStructures函数的代码。这通过向原始大小添加另外100个大小来重新分配结构。
if (reallocateStructures(&callLogSearch, &callLogSearchData, &switches, ×StructHasBeenReallocated, currentStructIndexValue, dataRow) == 0)
{
//Structures have been reallocated so reset the index
currentStructIndexValue = 0;
}
以下是重新分配结构的实际代码
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;
if (initFromIndex == newSize - 1)
{
printf("debugging here\n");
}
}
*callLogSearch = callLogSearchTemp;
*callLogSearchData = callLogSearchDataTemp;
*switches = switchesTemp;
return 0;
}
else
{
return 1;
}
}
下面是代码,在它循环遍历所有MySQL行之后,结构被重置并重新初始化为100的大小。
//Check if function has looped round already and if so reset all structures
if (dataRow > -1)
{
numberOfTimesEverythingHasReset++;
callLogSearchData = NULL;
callLogSearch = NULL;
switches = NULL;
callLogSearchData = realloc(callLogSearchData, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
callLogSearch = realloc(callLogSearch, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
switches = realloc(switches, INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//initialiseNewStructure(&callLogSearch, &callLogSearchData, &switches);
//callLogSearchData = (callLogSearchDataStruct*)realloc(callLogSearchData, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
//callLogSearch = (callLogSearchResultStruct*)realloc(callLogSearch, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
//switches = (switchIDStructure*)realloc(switches, INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//Initialise all elements within structures
for (initFromIndex = INITIAL_CALL_STRUCT_SIZE; initFromIndex < INITIAL_CALL_STRUCT_SIZE; initFromIndex++)
{
callLogSearchData[initFromIndex].aParty = NULL;
callLogSearchData[initFromIndex].bParty = NULL;
callLogSearchData[initFromIndex].cleardownCause = NULL;
callLogSearchData[initFromIndex].date = NULL;
callLogSearchData[initFromIndex].duration = 0;
callLogSearchData[initFromIndex].outboundLegs = NULL;
callLogSearchData[initFromIndex].time = NULL;
callLogSearch[initFromIndex].date = NULL;
callLogSearch[initFromIndex].dRowIndex = dataRow;
}
timesStructHasBeenReallocated = 1;
currentSize = 0;
}
currentStructIndexValue = 0;
我不确定为什么当它第一次将结构重置回大小为100时进入if语句时,在17 MySQL行之后内存超出界限所以我是段错误的。
感谢您提供的任何帮助。
更新 我根据@Rohan的答案解决了for循环的问题,但我现在遇到了一个稍微不同的问题。
我现在在尝试向结构添加数据时得到了一个不同的区域,但我不确定结构是否与它有关,因为它似乎是现在导致seg的出界问题的MySQL数组故障。
失败的行是
callLogSearchData[dataRow].bParty = strdup(rowReport[bPartyColIndex]);
当我在GDB中检查rowReport时,它内部似乎有垃圾,并且在第7个索引(bPartyColIndex
在索引9处)我开始看到out bounds错误。
每次为每个mysql行循环时都会分配rowReport,如下面的代码所示
sqlLen = asprintf(&sql, "SELECT Tmp.SwitchID, Tmp.CorrelationID, SeizeUTC as Date, "
"SeizeUTC as Time, Direction, ACMToAns/100 as ACMToAns, Duration/100 as Duration, "
"CleardownCause, AParty, Tmp.BParty FROM TMP_Log AS Tmp ORDER BY SeizeUTC, "
"Tmp.SwitchID, Tmp.CorrelationID, Direction, SeizeCSec LIMIT %i, %i",
index, count);
SL_DebugAll(DBG_INFO, sql);
if ((mysql_real_query(HandleDB, sql, sqlLen))) return 1;
resultReport = mysql_store_result(HandleDB);
if (mysql_num_rows(resultReport) == 0 || index > atoi(limit))
{
SL_DebugAll(DBG_INFO, "Data retrieval for call log complete");
break;
}
else
{
numRows = mysql_num_rows(resultReport);
swID = -1;
corrID = -1;
dataRow = -1;
if (numRows > 0)
{
maxTargets = 1;
}
audioRow = mysql_fetch_row(audioResult);
sspSwitchID = atoi(audioRow[switchIDColIndex]);
sspCorrID = atoi(audioRow[correlationIDColIndex]);
inbound_counter = 0;
while (rowReport = mysql_fetch_row(resultReport))
答案 0 :(得分:0)
在你的最后一段代码中你有
if (dataRow > -1)
{
numberOfTimesEverythingHasReset++;
callLogSearchData = NULL;
callLogSearch = NULL;
switches = NULL;
callLogSearchData = realloc(callLogSearchData,
INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
callLogSearch = realloc(callLogSearch,
INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
switches = realloc(switches,
INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//Initialise all elements within structures
for (initFromIndex = INITIAL_CALL_STRUCT_SIZE;
initFromIndex < INITIAL_CALL_STRUCT_SIZE;
initFromIndex++)
{
....
您将callLogSearchData
设置为NULL
,因此重新分配无效。
你正在分配INITIAL_CALL_STRUCT_SIZE
个元素,但你的for循环计数器从INITIAL_CALL_STRUCT_SIZE
开始,因此循环不会执行。
答案 1 :(得分:0)
我已经设法找出问题所在,遗憾的是这是一个非常基本的错误。
由于代码崩溃的地方,我认为它必须与我重新初始化结构的方式有关,可能是因为我使用指针的方式。
然而,事实并非如此,相反,代码中的其他地方我使用名为fileRow
的索引向其中一个结构添加了一些数据。每次将一个值添加到结构中时我都会增加fileRow但是当我重新分配结构时我忘记重置为0,所以当我重新分配结构大小为100时,我插入到fileRow所在的结构中设置为1300,所以每次我循环时,我都会破坏记忆,直到它被分割出来。
感谢您的帮助和建议。