0

我是 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;

我不确定为什么当它第一次进入 if 语句以将结构重置回 100 的大小时,在 17 MySQL 行之后内存超出范围,所以我出现了段错误。

感谢您的任何帮助,您可以提供。

更新 我已经按照@Rohan的回答解决了for循环的问题,但我现在遇到了一个稍微不同的问题。

我现在在尝试向结构中添加数据时得到了一个不同的区域,但我不确定这些结构是否与它有关,因为它似乎是 MySQL 数组现在有一个越界问题导致了段错误。

它失败的地方是

callLogSearchData[dataRow].bParty = strdup(rowReport[bPartyColIndex]); 

当我在 GDB 中检查 rowReport 时,它内部似乎有垃圾,并且在第 7 个索引处(bPartyColIndex在索引 9 处)我开始看到出界错误。

rowReport 在每次循环时为每个 mysql 行分配,如下面的代码所示

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))
4

2 回答 2

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++)
        {
           ....

您设置callLogSearchDataNULL因此重新分配不相关。

而且您正在分配INITIAL_CALL_STRUCT_SIZE元素数量,但是您的 for 循环计数器从INITIAL_CALL_STRUCT_SIZE如此有效地开始 for 循环不会执行。

于 2013-09-16T13:21:23.757 回答
0

我已经设法找出问题所在,不幸的是,这是一个非常基本的错误。

由于代码崩溃的地方,我认为它必须与我重新初始化结构的方式有关,可能是因为我使用指针的方式。

然而,情况并非如此,相反,在代码中的其他地方,我使用名为fileRow. 每次向结构中添加一个值时,我都会增加 fileRow 但是当我重新分配结构时我忘记重置回 0,所以当我将结构重新分配为大小 100 时,我插入到 fileRow 所在的结构中设置为 1300 所以每次我循环我都会破坏内存,直到它出现段错误。

感谢您的帮助和建议。

于 2013-09-17T15:36:23.157 回答