2015-04-23 94 views
0

我有保存指向其他樹節點下面的樹節點的結構:內存分配

struct node { 
    // ... 
    struct node* children[20]; 
} 

的想法是,我要檢查是否存在node*children內部和基於並且更深入到樹中。所以,當我分配node我想有children與20 NULL值。 目前,我不要那樣做

  1. 我應該如何才能沒有得到像Conditional jump or move depends on uninitialised value(s)(Valgrind的)錯誤地分配這個數組?
  2. 每次分配新節點時使用struct node** children並分配固定大小會更好嗎?

編輯:一個地方Valgrind的抱怨的例子:

for(int i=0;i<20;i++) 
    if(node->children[i] != NULL) 
    do_something_with_the_node(node->children[i]); 
+1

如果您動態分配結構,請使用'calloc'而不是'malloc'。或者使用'memset'將所有內容設置爲零。 –

+0

'有條件的跳轉或移動取決於未初始化的值(s)'由valgrind報告意味着你有一個'if'語句,你在比較'node [x]',對嗎?你可以發佈該代碼嗎? – rubikonx9

+0

@ g.tsh是的。我已經添加了一個例子。 – syntagma

回答

1

當您分配struct node的新實例時,您必須將包含的指針設置爲NULL以將它們標記爲「不指向任何位置」。這將使Valgrind警告消失,因爲指針將不再未初始化。

事情是這樣的:

struct node * node_new(void) 
{ 
    struct node *n = malloc(sizeof *n); 
    if(n != NULL) 
    { 
    for(size_t i = 0; i < sizeof n->children/sizeof *n->children; ++i) 
     n->children[i] = NULL; 
    } 
    return n; 
} 

不能移植應用要麼memset()n->children也不calloc(),因爲這些都會給你「所有位零」,這是不一樣的「指針NULL」 。

+0

謝謝,還有一個問題:'memset()'/'calloc()'和設置指向NULL的指針有什麼區別? – syntagma

0

你的結構定義是有效的(儘管它很難說沒有更多的情況下,如果它符合您的要求)。

Valgrind不會抱怨你的結構定義,它可能會抱怨你如何實例化該類型的變量。確保所有陣列成員都已初始化,並且投訴很可能會消失。

+0

目前我不使用{c,m} alloc來分配這個數組的內存(據我所知,我不必在這種情況下)。我後來做的事情就像是:'node-> chlidren [10] = some_node_pointer;'(其他索引處的值可能保持未初始化)。 – syntagma

+0

這是valgrind抱怨的。在你添加的例子中,你可以調用'do_something_with_the_node()',具體取決於它是否爲NULL或其他。你似乎期望數組成員在沒有時會自動初始化爲NULL。你需要明確地將整個數組初始化爲NULL(例如,使用'memset()'或'calloc()')。 – mfro

0

問題是您正在使用if條件中的未初始化值。

當你實例化一個struct node時,其成員struct node* children[20];是一個20 struct node *的數組,它們都是未初始化的。

這將是從這個沒有什麼不同:

char *x; 

if (x == NULL) { 
    /* Stuff */ 
} 

在這一點上,可以x字面上有任何價值。在你的例子中,數組中的任何元素都可以有任何值。

要解決這個問題,你需要使用它們,例如像在此之前初始化數組的元素:

for (int i = 0; i < 20; ++i) { 
    node->children[i] = NULL; 
} 

或更短:

memset(node->children, 0, 20); 

如果更改了成員,正如你所建議的,node **children,情況不會有太大的不同 - 你仍然需要初始化所有的成員,包括數組的元素。你可以通過使用calloc來縮短它,它會將所有字節初始化爲0;然後再次,你需要一些正確的釋放代碼(並記住這樣做),所以我認爲權衡是不值得的。

+0

由於某種原因,memset版本不起作用。 – syntagma

+0

哦。 IDK。也許這是@unwind提到的問題 - 設置所有的零而不是顯式的NULL是不可移植的。 – rubikonx9