2016-01-28 71 views
0

好的,我正在c中創建一個向量數據結構(或動態列表)。 這裏是我的節點結構:嘗試訪問結構中的空指針時出現Segfault

struct vector_node{ 
    void *value; 
}; 

,這裏是我的矢量結構:

struct vector{ 
    int size; 
    int capacity; 
    vector_node *start; 
    vector_node *end; 
    vector_node **nodes; 
}; 

這裏是我如何創建和分配內存的向量:

vector* createVector(){ 
    vector *vector = malloc(sizeof(vector)); 
    vector->size = 0; 
    vector->capacity = 8; 
    vector->start = NULL; 
    vector->end = NULL; 
    vector->nodes = malloc(8*sizeof(vector_node)); 
    int i = 0; 
    vector->nodes[0]->value = (int) &i; 
} 

最後兩條線就是我遇到麻煩的地方。似乎每當我嘗試初始化值變量,我遇到一個段錯誤。

+1

'vector-> nodes [0]'是一個指針。它指向什麼? – immibis

+0

'malloc(8 * sizeof(vector_node));'分配錯誤的字節數量(也是你的誤解的症狀)。 'vector_node **節點;'說節點'將指向一個包含** 8個指針**的數組。但是,您將malloc語句用於** 8個vector_nodes **的數組。 –

回答

2

vector->nodes = malloc(8*sizeof(vector_node)); 

是錯誤的。您需要分配一個vector_node*的數組,因爲vector->nodes的類型爲vector_node**。爲了避免這樣的錯誤的推薦方法是:

Type* x = malloc(count*sizeof(*x)); 

你的程序,那將是:

vector->nodes = malloc(8*sizeof(*(vector->nodes))); 

vector->nodes[0]->value = (int) &i; 

是錯在幾個方面。

  1. 在嘗試解引用它之前,您尚未爲vector->nodes[0]分配內存。
  2. 您正在將指針轉換爲int,這可能會導致地址被截斷。
  3. vector->nodes[0]->value的類型是void*但您正嘗試將它分配給int
  4. 您正在將功能本地變量i的地址存儲在要從函數返回的struct中。函數返回時,您將有一個懸掛指針。

您需要:

vector->nodes[0] = malloc(sizeof(*(vector->nodes[0]))); 
vector->nodes[0]->value = <some memory that will outlast the function call>; 

最後,您沒有return聲明其返回類型比void不同的功能。如果調用代碼使用類似:

vector* v = createVector(); 

你的程序將表現出不確定的行爲。

2

在這裏你有一個兩級分配。 vector->nodesvector_node**,因此通過提領它可以獲得vector_node*,您試圖通過->value連續取消引用以獲取實際實例的字段。

但你怎麼分配一切? nodes包含指針不是真實的對象,所以在爲節點指針分配空間之後,還必須分別分配每個節點。

所以分配應該是這樣的:

const size_t LENGTH = 8; 
vector->nodes = malloc(LENGTH * sizeof(vector_node*)); // note it's vector_node* not vector_node, as we're allocating memory for pointers 
for (size_t i = 0; i < LENGTH; ++i) 
    vector->nodes[i] = malloc(sizeof(vector_node)); // here we're allocating the real object 

// now you can correctly have two chained dereferences 
vector->nodes[0]->value = (int)&i; 

介意重新分配將需要兩個步驟,也以相反的順序。

1

要處理您的想法,您需要做幾件事情。的vector

改變定義如下:

struct vector{ 
    int size; 
    int capacity; 
    vector_node *start; 
    vector_node *end; 
    vector_node *nodes; // <----- this is a pointer that can be offset like an array 
}; 

變化createVector()的定義如下:

vector* createVector(){ 
    vector *vector = malloc(sizeof(vector)); 
    vector->size = 0; 
    vector->capacity = 8; 
    vector->start = NULL; 
    vector->end = NULL; 
    vector->nodes = malloc(8*sizeof(vector_node)); 
    int i = 0; 
    vector->nodes[0].value = (void*) &i; // <----- offset the pointer like an array 
             // <----- (which is what you allocated for) 
} 

這樣做的原因是你已經分配的內存爲vector_node類型的8個目標和將基址指針分配給vector->nodes。因爲內存包含對象而不是指向對象的指針,所以需要直接偏移指針以獲取單個對象。

相關問題