0

私はCが初めてで、何日も仕事をしようとして苦労してきたプロジェクトに取り組んでいますが、どこに問題があるのか​​ わかりません。

基本的に、アプリケーションが行うことになっているのは、データベースからデータを読み取り、値を構造体に挿入することです。一部の行はそれぞれに関連しているため、構造内には、データベースからの他の値を含むリンクされたリストがあります。

データベースからいくつのレコードを取得するかわからないので、最初に構造を 100 アイテムになるように malloc し、100 に達すると構造を再割り当てしてさらに 100 を追加するインデックスを追跡します。アイテム。再割り当てビットは機能しているようですが、構造内のリンクリストに何かを挿入しようとすると、segfault が発生します。

以下は、メイン構造体の定義です。

typedef struct CallLogSearchDataStruct
{
    char * date;
    char * time;
    char * bParty;
    char * aParty;
    float duration;
    char * cleardownCause;
    struct CallLogSearchOutboundStruct * outboundLegs;
} callLogSearchDataStruct;

以下は、リンクされたリスト (CallLogSearchOutb​​oundStruct) のコードです。

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, &timesStructHasBeenReallocated, 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 を介してプログラムを実行しようとしましたが、すべてのメッセージが何を意味するのか完全にはわかりません。Google を実行しても、何かが見つかりましたが、問題を理解するのに役立ちませんでした。

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

行 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";
    }
}

すべてのコードで申し訳ありませんが、問題がどこにあるのか正確にはわかりません。コア ダンプを見ると、構造内の値の一部を調べると、文字化けした混乱のように、何かがメモリを破壊しているように見えます。

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

4

1 に答える 1