2011-07-30 100 views
1

我寫具有以下動態配置結構的應用:ç未知大小的結構

typedef struct { 
    char apphash[41]; 
    char filenames_count; 
    char * filename[64]; 
} config; 

但這個代碼是錯誤的,我無法弄清楚如何將數據從複製和C->文件名[0]正確; c是一個指向配置結構,動態分配的像

config * c = (config *) malloc(42 + 64 * 2) // alloc for 2 filenames. can realloc() later. 

它出現segfaults如果我使用類似strcpy(c->filename[0],"file1.txt")

有人可以幫助我嗎?

目前,我使用的是直接地址計算,像

strcpy(
    (char*) 
    ((unsigned long) c + 42 /* apphash + filenames_count */ + 
    64 * 0 /* first item */), 
    "file1.txt" 
); 

和它的作品當然。

你看,我比C程序員更喜歡程序員,但是我希望這段代碼更加人性化。這段代碼看起來不好,因爲我是C的新手。


哦,我給了一個壞的描述。對不起,那:(
真正的代碼如下所示:

config * c = (config*) malloc(42 + 64 * 2); 
// we may realloc() it later if we are going to add more filenames. 

// failing example how I do copy one default filename 
strcpy(c->filename[0],"file1.txt"); 

// working example (i386) 
strcpy((char*)((unsigned long) c + 42 + 64 * 0),"file1.txt"); 

我使用完全靜態的結構類型,因爲它會直接從下一次文件加載這就是爲什麼我真的不能使用指針。內部結構,我需要真正的數據被放置在那裏。
我確實檢查所有長度,沒有實際代碼中的BOF,我只是省略了所有這些東西。 。

再次感謝並對不好的問題信息抱歉離子。

+0

我不確定它是否是C標準頭文件的一部分,但請查看'offsetof'來幫助自動計算。 –

+0

你的'strcpy'似乎指向你的一個可能的誤解。 'char * filename [64]'是一個由64個char *組成的數組,不是一個指向'char'數組的指針。你的'64 * 0'似乎表明你認爲它是後者。作爲一個提示,'cdecl'是一個解析C聲明並用簡單的英語將它們描述給你的程序,當你不習慣C語言時它非常有用。http://cdecl.ridiculousfish.com/ –

+0

@unknown_c_newbie甚至未註冊的用戶可以對他們的問題提出更改建議,但是您應該繼續,並將OpenID(或密碼)與您的帳戶相關聯。 – phihag

回答

4

我想你有很多文件名,因爲你有filenames_count。嘗試

config_obj.filename[0] = strdup("file1.txt") 
+1

,並記住'free()'複製的字符串 – CAFxX

+1

+1,但'strdup'是一個非標準(如果易於實現)函數,可能不會出現在您的編譯器/平臺上(如果您的編譯器/平臺碰巧吸引嚴重)。 –

2

眼下config這意味着你所定義的結構。您不會向我們顯示標識符,指的是config類型的實際變量。

所以,首先我們需要一個config類型的實例。你要麼做

config c; 
... c.filename ... 

注意結構接入運營商是.,否則你會做這樣的事情

config *p = malloc(config) 
/* error checking */ 
...c->filename ... 

其中->是指針解引用和接入運營商。第一種形式是首選,除非你有一個理由要動態分配(這,唉,在c發生很多)。

然後,你必須弄清楚你想要filename是什麼。因爲它已經分配了64個字符指針的空間,其中不指向指向分配的內存(除非是最純粹的acident,然後不是你指的內存)。你可能想{*} char filename[64](單個文件名允許爲最多63個字符長(留有餘地空)終止)在這種情況下,你可以使用

strcpy(c.filename,"file1.txt"); 
/* or */ 
strcpy(p->filename,"file1.txt"); 

取決於你如何在分配結構第一個地方。

如果你真的想要的文件名的列表,那麼你可能想char *filenames[64],但你必須分配緩衝區爲每名纔可以使用它

c.filenames[0] = malloc(sizeOfString); 
/* error checking */ 
strcpy(c.filenames[0],... 

或作爲另一個海報建議

c.filenames[o] = strdup(... 

如果您從多個部分構建文件名,並且可以從開始計劃總長度,則第一種形式可能會更好。


{*}後面你可能想要取消這個固定長度的緩衝區,但現在就離開。

+0

這樣做對問題的評論會更好,而不是回答。 – Amy

+0

@Inuyasha:迭代改進。 – dmckee

3

在你的結構中,你正在分配一個指向字符的指針數組,而不是一個字符數組。你必須明確地也分配指針的目標,或者至少是,使結構還含有字符本身的數組:

char filename[64][MAX_PATH+1]; 

更換MAX_PATH與任何文件名的最大長度。請注意,這不是一個非常優雅的解決方案,儘管它非常簡單,因爲你浪費了很多空間。

你直接地址計算做一些不同的東西:它是直接放置在字符串中分配給指針的空間(這是一個非常錯誤的事情™做)

+0

我相信它的目的是成爲一個字符指針數組。結構中的另一個字段是'filenames_count'。 – Amy

+2

我知道:第一個strcpy失敗的原因是因爲OP很可能實際上沒有爲字符串分配內存,並且該數組中的指針未初始化。 – CAFxX

1

它目前沒有,因爲你不是爲文件名分配內存。無論是使用strdup或malloc + strcpy(我會使用strdup)。

您的文件名字段是指向零終止字符串的指針數組。您需要爲該字符串分配內存並將該字符串複製到該內存。您將新字符串的地址保存在其中一個指針中,例如文件名[0]。

直接內存地址代碼不起作用。它只是不會崩潰,但!該代碼只是覆蓋指針數組。不要寫這樣的代碼。永遠不會!!編寫這樣的代碼在道義上相當於吃獨角獸。