2013-11-28 29 views
-1

我已經看了所有谷歌,似乎無法理解爲什麼malloc在我的代碼失敗。我已經包含了我認爲有助於理解問題的部分代碼。Malloc打破它應該不會

奇怪的部分是我以完全相同的方式使用了malloc 5行以上,並且第一次成功,但第二次失敗。當我通過gdb時,parent-> left_tree的指針在malloc-ed之前是0x0,並且它工作正常,然後當涉及到parent-> right_tree時,它每次都會出現給定的隱藏錯誤消息。我嘗試過使用malloc中的不同值進行試驗,例如malloc(64)和malloc(10000),結果是相同的。

這裏是代碼的功能,其中的malloc失敗:

int 
prefix_input(expr_tree_T parent) 
{ 

    char *token = get_next_token(); 
    int int_value; 
    double dub_value; 
    int type = node_type(token); 

    if (type == -1) 
    { 
     fprintf(stderr, "ERROR: '%s' is invalid input.\n", token); 
     exit(2); 
    } 

    parent->type = type; 

    if (type == OPERATOR) 
    { 
     parent->value.operator = token[0]; 
     parent->left_subtree = malloc(sizeof(expr_tree_T)); 
     mem_check(parent->left_subtree, "left subtree"); 

     prefix_input(parent->left_subtree); 

     parent->right_subtree = malloc(sizeof(expr_tree_T)); //<-- ***Right here*** 
     mem_check(parent->right_subtree, "right subtree"); 

     prefix_input(parent->right_subtree); 
    } 
    else if (type == INTEGER) 
    { 
     sscanf(token, "%d", &int_value); 
     parent->value.int_value = int_value; 
     parent->left_subtree = NULL; 
     parent->right_subtree = NULL; 
    } 
    else if (type == DOUBLE) 
    { 
     sscanf(token, "%lf", &dub_value); 
     parent->value.double_value = dub_value; 
     parent->left_subtree = NULL; 
     parent->right_subtree = NULL; 
    } 

    return 0; 
} 

下面是分配給用於由具有存儲器中的結構的代碼:

typedef struct expr_tree_node 
{ 

    struct expr_tree_node *left_subtree; 
    struct expr_tree_node *right_subtree; 

    int type; 

    union 
    {   
     char operator; 
     int int_value; 
     double double_value; 
    } value; 

} * expr_tree_T; 

這是我的所有包含的頭files:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

這就是代碼編譯的方式:

gcc -Wall -std=c99 -D_POSIX_SOURCE A12P2.c -o a12p2 -g 

這是使用GDB進行調試的示例。我可以觀察到parent-> right_subtree的指針是0,正如我研究的一般情況下使用malloc是最安全的。

prefix_input (parent=0x804c008) at A12P2.c:171 
171   parent->right_subtree = malloc(sizeof(expr_tree_T)); 
(gdb) print parent->left_subtree 
$7 = (struct expr_tree_node *) 0x804c160 
(gdb) print parent->right_subtree 
$8 = (struct expr_tree_node *) 0x0 
(gdb) s 
a12p2: malloc.c:2369: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)- 
>bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size 
== 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct 
malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 
1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed. 

Program received signal SIGABRT, Aborted. 
0xb7fdd424 in __kernel_vsyscall() 
+1

程序中的某些東西正在破壞堆。使用valgrind來幫助找到它。 – Barmar

+0

你如何調用'prefix_input()'? –

回答

1

這種類型的錯誤指示您的應用程序已損壞時malloc()使用的數據結構。這通常發生是因爲你已經寫入了已分配的內存塊,或者寫入了已釋放的內存。

在這種情況下,看來你不爲你的結構分配足夠的內存:

parent->left_subtree = malloc(sizeof(expr_tree_T)); 

鑑於這一功能的原型,它看起來好像expr_tree_T是一個指向結構的typedef ,而不是結構本身。如果確實如此,那麼sizeof(expr_tree_T)最終會成爲該指針的大小,而不是結構的大小,因此您分配的內存比實際需要的少得多!

我強烈建議您更改此類型的定義,使其成爲結構的名稱(因此該函數現在將接受expr_tree_T *作爲參數)。如果您發現星星令人討厭,請鍵入指向expr_tree_ref之類的指針並根據需要使用該指針。在你的頭文件,這可能看起來像:

typedef struct expr_tree { 
    .... 
} expr_tree_T, *expr_tree_ref; 

做不到這一點,你就需要專門引用結構在sizeof()表達:

malloc(sizeof(struct what_an_expr_tree_T_points_to)) 

這是(甚至一旦你使用真正的名稱,不管它是什麼)比sizeof(expr_tree_T)更混亂。

+0

非常感謝,我改變了這一點,重新調整了程序的某些部分,工作正常。我想我只需要刷一下我對指針等的理解。當你在開頭說,我的應用程序可能損壞malloc()使用的數據結構,你是什麼意思?你是否建議我的程序恰好訪問了malloc試圖用於自己目的的一些內存?這是偶然的,該程序是否可能意外地從我的其他程序中訪問了內存? –

+0

內存分配器將「簿記」數據保留在其分配的塊的內存中。超出分配塊的末尾,或在開始之前寫入,可能會損壞此數據。系統內存保護可防止您從其他程序訪問內存,但通常可以做的最糟糕的事情就是讓自己陷入困境。 – duskwuff

相關問題