簡體   English   中英

C 字符數組在傳遞到 function 后損壞

[英]C char array getting corrupted after being passed into function

我正在嘗試實現一個類似於 20 個問題的程序,其中加載了問題和答案猜測的文本文件,復制到 char 數組中(其中新的空格行被替換為 '/0' 以便拆分問題到單獨的字符串)。 將文本文件復制到數組后,該數組工作正常。 設置樹結構將短語組織成是/否問題樹,其中左邊的孩子是回答是,而右邊是回答不是,葉子是程序最后用來猜測的猜測。

我遇到的問題是,在構建樹(從 InitTree 調用 treeBuilder)之后,復制文本文件中的短語的數組內容已損壞。

在調用 InitTree 之前,數組內容如下所示:

是毛茸茸的嗎? 它喵喵叫嗎? a cat a dog 它有象牙嗎? 它有大耳朵嗎? 大象 犀牛 鱷魚

調用后,它看起來像這樣:

是毛茸茸的嗎? -???`?p?a dog 它有象牙嗎? 它有大耳朵嗎? 大象 犀牛 鱷魚

我一直在測試它停止工作的地方,在 treeBuilder 中,數組的所有元素都完好無損,但是一旦對 treeBuilder 的 function 調用結束,數組就會損壞。 每當我分配 memory 時,我都嘗試通過使用 calloc 來保護 memory,甚至通過創建字符數組 static,這在發生這種情況的類似情況下也有效。 但我所有的預防措施似乎都沒有奏效,我不確定問題出在哪里。 我已經嘗試在 stackoverflow 上查看類似案例,但我找不到與我的問題相關的任何內容。

出於顯而易見的原因,當程序實際開始使用樹時,這最終會導致段錯誤。

我試過運行 gdb,但無論出於何種原因,它都不會讓我逐行運行 go,因為它找不到行信息,只是跳過所有內容,直到提示輸入或出現 memory 錯誤或其他內容,所以運行 gdb 在這里不是很有幫助。 我猜這可能是因為主要的 function 在包含的文件中或其他東西中。 但這不是重點。

這是與問題相關的代碼:

struct treeStruct {
    char *string;
    struct treeStruct *left, *right;
};

typedef struct treeStruct *TreeType;

// Builds a tree
void treeBuilder(TreeType tree, char **phrase, long level){
    // Gets the level (number of tabs) of the next phrase
    long nextLevel = countTabs(*phrase + strlen(*phrase) + 1);

    tree->string = *phrase + level; // Assigns the response pointer to the tree array

    // Move the pointer to the next string, since the the strings need to be
    // put into the tree in linear order
    (*phrase) += strlen(*phrase) + 1;

    if (level >= nextLevel){
    // Compares the current level with the level of the next string
            // to determine if returning up the tree is necessary;
            // This should be the answer to a question.
            tree->left = NULL;
            tree->right = NULL;
            return;
    }
    else{
            // Makes sure the left and right pointers of the struct have
            // allocated space
            tree->left = calloc(1, sizeof(TreeType));
            tree->right = calloc(1, sizeof(TreeType));

            // Adds the yes and no branches to the tree, recursion will take care
            // of adding sub-branches
            treeBuilder(tree->left, phrase, level + 1);
            treeBuilder(tree->right, phrase, level + 1);
    }

    return;

}


TreeType InitTree (char *file){
    if(file == NULL){
            printf("File '%s' does not exist.\n", file);
            exit(2);
    }

    FILE *fp;
    fp = fopen(file, "r");

    // Create a space in memory for the loaded questions to occupy
    static char *phrases;
    phrases = (char *)malloc(MAXSTR * MAXNUMQS * sizeof(char));

    copyText(fp, phrases);

    fclose(fp);

    // Create space in memory for the tree structure
    TreeType tree;
    tree = (TreeType) calloc(1, sizeof(TreeType));

    // Create a pointer to a pointer so that treeBuilder can
    // change what the first pointer is pointing to, so the strings in
    // phrases can be added in order throughout the recursion
    static char *phrase_ptr, **phrase_ptr2;
    phrase_ptr = &phrases[0];
    phrase_ptr2 = &phrase_ptr;

    //Build the tree
    treeBuilder(tree, phrase_ptr2, 0);

    topNode = tree;

    return tree;
}

對不起,如果這是 tl;dr,但我想盡可能清楚地說明我的問題。

我注意到的一件事是您正在使用sizeof(TreeType) ,但TreeType是指向結構的指針而不是結構本身。 這意味着您正在創建一個指向任何地方的指針,並且取消引用該指針將導致未定義的行為。 剛剛閱讀問題的 rest 肯定會解釋段錯誤。

我認為你最好不要將你的結構類型定義為指針,並且更明確地使用指針。

例如。

typedef struct treeStruct TreeType;

void treeBuilder(TreeType *tree, char **phrase, long level){
    ...
    if (!tree->left) {
        // calloc returns a pointer to a new bit of memory that has been 
        // assigned on the heap
        TreeType *temp = calloc(1, sizeof(TreeType));
        // assignments below not explicitly needed as you're using calloc
        temp->string = NULL;
        temp->left = NULL;
        temp->right = NULL;

        tree->left = temp;
    }
    ...
}

這是一個關於typedef-ing 指針的問題。 似乎在 C 中比較常見,用來暗示數據類型是不透明的,不應該被用戶取消引用(只能由用戶傳遞給它的 API 調用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM