0

私はCを初めて使用しますが、現在、構造とメモリ割り当てに関連する問題を抱えているCプログラムに取り組んでいます。

私のコードには、特定の条件が満たされたときに抜け出す永続的な while ループがあります。この while ループ内でデータベースをチェックし、while ループを使用して MySQL の行をループします。

プログラムが最初にロードされると、3 つの構造体が作成されます。構造体の 1 つには、リンクされたリストも含まれており、サイズが 100 に初期化されています。

私のプログラムは MySQL 行をループするときに、100 レコードが追加されたかどうかをチェックし、追加された場合は再割り当てを行い、サイズをさらに 100 行増やします。すべての MySQL 行をループすると、メインの 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 行の後にメモリが範囲外になる理由がわからないので、segfault します。

ご協力いただきありがとうございます。

更新 @Rohanの回答に従ってforループの問題を修正しましたが、現在は少し異なる問題が発生しています。

構造にデータを追加しようとすると、別の領域が得られますが、構造がそれと関係があるかどうかはわかりません。MySQL 配列に範囲外の問題があり、セグ フォールトが発生しているようです。

失敗している行は

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

GDB で rowReport を調べると、その中にゴミがあるようで、7 番目のインデックス (bPartyColIndexインデックス 9 にあります) で、境界外エラーが表示され始めます。

以下のコードに示すように、各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))
4

2 に答える 2

0

残念ながら、これはかなり基本的な間違いです。

コードがどこでクラッシュしたかという理由で、おそらくポインターの使用方法が原因で、構造を再初期化する方法に関連するものに違いないと思いました。

ただし、代わりに、コードの別の場所で、 というインデックスを使用して構造体の 1 つにデータを追加していましたfileRow。値が構造体に追加されるたびに、fileRow をインクリメントしましたが、構造体を再割り当てしたときに 0 にリセットするのを忘れていたので、構造体をサイズ 100 に再割り当てしたとき、fileRow があった場所の構造体に挿入していました。 1300 に設定したので、ループするたびにセグメンテーション違反が発生するまでメモリを破壊しました。

あなたの助けと提案をありがとう。

于 2013-09-17T15:36:23.157 に答える
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非常に効果的にforループが実行されません。

于 2013-09-16T13:21:23.757 に答える