增加结构尺寸,然后将它们重置回原始尺寸并再次增加尺寸

时间:2013-09-16 12:18:32

标签: c structure realloc

我是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, &timesStructHasBeenReallocated, 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))

2 个答案:

答案 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,所以每次我循环时,我都会破坏记忆,直到它被分割出来。

感谢您的帮助和建议。