2012-02-20 52 views
0

我正在開發一個多線程程序。它能夠正確地關閉所有線程,但是,它最後會發生段錯誤。通過註釋掉我的代碼的某些部分,我發現它是這個領域與開放交易的代碼內/關閉文件:打開/關閉文件時發生分割錯誤?

char *pid_fname; 
FILE *file; 

sprintf(pid_fname, "%s%d%s", "/proc/", pid, "/stat"); 
file = fopen(pid_fname, "r"); 

/* code */ 

fclose(file); 

我試着在gdb調試,但是我只有打印出來後,得到這個'where'後段錯誤:

#0 0x2f312f63 in ??() 
#1 0x74617473 in ??() 
#2 0xbfaee700 in ??() 
#3 0xbfaee77c in ??() 
#4 0x006a7810 in ??() 
#5 0x00000000 in ??() 

任何人都可以給我一些關於從哪裏去的指針嗎?

+0

這是很可能你會得到像'警告的警告:「pid_fname」在此被用來初始化function'。你應該多注意警告多少次,它可以幫助你防止像這樣的運行時崩潰。此外,要獲取調試符號,您需要使用[調試選項](http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options)(假設您使用的是gcc) – 2012-02-20 05:44:30

回答

3

您有文件名沒有後備存儲。你已經創建了一個指針,但沒有分配空間。這意味着它幾乎可以肯定指向某處你不想寫入的地方:-)

假設你知道進程ID的最大範圍(例如說5個數字),最簡單的修復就像(並且改變參數略有因爲/proc//stat固定字符串):

char pid_fname[sizeof("/proc/99999/stat")]; 
sprintf(pid_fname, "/proc/%d/stat", pid); 

否則,你會如果你耗盡內存需要動態分配根據實際pid值足夠的空間,代碼防守。

由於系統往往有進程ID的固定範圍,我會選擇固定大小的緩衝區。如果你真的想從錯誤保護,同時還擔心的不是動態分配的,你可以使用類似:

char pid_fname[sizeof("/proc/99999/stat")]; 
if ((pid < 0) || (pid > 99999)) { 
    fprintf (stderr, "WTH? What sort of PID was that (%d)?\n", pid); 
    exit (1); 
} 
sprintf(pid_fname, "/proc/%d/stat", pid); 
+0

詳細的文章,謝謝! – Kobi 2012-02-20 05:49:45

3

sprintf要求其第一個參數是一個指向一個呼叫者分配的緩衝區。你甚至不初始化pid_fname

1
char *pid_fname; 
sprintf(pid_fname, "%s%d%s", "/proc/", pid, "/stat"); 

pid_frame是一個未初始化的指針。在這種情況下,提供的參數不能複製到緩衝區。