2013-05-28 64 views
3

該程序在我的UNIX計算機上導致seg錯誤。我將原因縮小到調用memset()的調用memset導致分段錯誤

爲什麼會發生這種情況?第一個「代碼塊」與第二個代碼塊幾乎相同,不是嗎?爲什麼沒有第一個調用memset段錯誤,如果第二個呢?

我查看了關於segfaulting memset調用的其他線程,但沒有一個與此類似。

如果你想知道爲什麼我寫了這樣一個小程序,它是從我一直在寫的另一個程序改編的,我用它來教自己如何將memcpy()應用到結構中。

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

typedef struct{ 
    int x; 
    char text; 
} FilesStruct; 

int 
main(int argc, char** argv) 
{ 
    FilesStruct *old_dir; 
    memset(old_dir,0,sizeof(FilesStruct)); 
    old_dir->x = 3; 
    old_dir->text = 'c'; 
    printf("old dir: %d,%c\n",old_dir->x,old_dir->text); 

    FilesStruct *new_dir; 
    memset(new_dir,0,sizeof(FilesStruct)); 
    new_dir->x = 7; 
    new_dir->text = 'g'; 
    printf("new dir: %d,%c\n",new_dir->x,new_dir->text); 

    return 0; 
} 

回答

9
FilesStruct *old_dir; 
memset(old_dir,0,sizeof(FilesStruct)); 

試圖寫入一個未初始化指針。這導致未定義的行爲,包括可能的崩潰。它的運氣(好或壞,取決於你如何看待它),這種行爲的第一個實例沒有崩潰。

您需要爲old_dir分配內存。要做到這一點,最簡單的方法是聲明它的堆棧

FilesStruct old_dir; 
memset(&old_dir,0,sizeof(old_dir)); 

上,或者你可以在堆上動態分配(確保調用free當你不再需要的對象)

FilesStruct *old_dir = calloc(1, sizeof(*old_dir); 
/* use old_dir */ 
free(old_dir); 

的同樣適用於new_dir進一步向下代碼。

+0

哦,我正打算使用的memset作爲初始化器,你猜我是非常錯誤。 所以我的聲明只聲明一個指針,而不是底層結構;因此,我需要在memsetting之前分配內存到0? –

+0

@Noob是的,這就是 – simonc

+0

感謝您的幫助! –

3

old_dirnew_dir都沒有被初始化,所以這是未定義的行爲。一個解決辦法是在棧上分配兩個變量:

FilesStruct old_dir; 
//... 
FilesStruct new_dir; 

,並使用操作者&以獲得地址調用memset時:

memset(&old_dir,0,sizeof(FilesStruct)); 
3
FilesStruct *old_dir; 

這定義了FilesStruct指針。它是未初始化的,所以它實際上並不指向FilesStruct的任何存儲。

memset(old_dir,0,sizeof(FilesStruct)); 

會告訴memset的在零出任何old_dir點,但作爲指針未初始化,你得到了一個未定義的行爲。

您需要爲指針提供存儲空間,例如

FilesStruct *old_dir = malloc(sizeof(FilesStruct)); 

在你的情況,你並不真的需要一個指針或動態分配的內存,你可能會做

FilesStruct old_dir; 
memset(&old_dir,0,sizeof(FilesStruct)); 
old_dir.x = 3; 
old_dir.text = 'c'; 
printf("old dir: %d,%c\n",old_dir.x,old_dir.text);