2013-02-14 73 views
0

我正在做一個小項目,我想知道爲什麼這段代碼導致我的程序崩潰。fscanf正在崩潰程序

PLAYER_FILE_PATH - 「player.txt」

sprite=yoshi.bmp 
width=64 
height=64 
frames=8 
alignment=1 
animate=1 

程序

 FILE *pfile = fopen(PLAYER_FILE_PATH, "r"); 
if (!pfile) 
{ 
    debug_printf("could not open player file for reading!\n"); 
    return; 
} 
fscanf(pfile, "sprite=%s\n\ 
       width=%d\n\ 
       height=%d\n\ 
       frames=%d\n\ 
       alignment=%d\n\ 
       animate=%d", 
       player_entity.entity_sprite.imgloc, 
       &player_entity.entity_sprite.width, 
       &player_entity.entity_sprite.height, 
       &player_entity.entity_sprite.frames, 
       &player_entity.entity_sprite.oscdir, 
       &player_entity.entity_sprite.osc); 
fclose(pfile); 
+0

你能展示一個「player_entity」的定義嗎? – 2013-02-14 12:17:02

+0

確保'player_entity.entity_sprite.imgloc'被正確分配(或者是一個與'player_entity'的生命週期相關的生命週期的緩衝區,或者是通過調用'malloc'來動態分配的)。 – LihO 2013-02-14 12:17:10

+0

專業提示:** [請選擇不破](http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html) **。 _您正在崩潰程序。 – sehe 2013-02-14 12:27:36

回答

4

我們需要查看您對player_entity的定義才能確定。你可能沒有正確定義「imgloc」,它需要指向一些安全分配的內存。例如,下面的定義將核心轉儲,除非imgloc正確初始化:

struct { 
    struct { 
    char *imgloc; 
    int width; 
    int height; 
    int frames; 
    int oscdir; 
    int osc; 
    } entity_sprite; 
} player_entity; 

如果更換上面東西imgloc線像

char imgloc[100]; 

但是這個核心轉儲將是可以避免的,我會要非常小心使用fscanf來讀取字符串,因爲如果字符串太長,它會溢出給定的緩衝區。也許試試fgets,而不是僅僅用於字符串部分,其餘部分用fscanf。

+0

我會使用fgets,但它讀取整個行,而不僅僅是我需要的部分 – 2013-02-14 12:42:17

+0

@OliverSikes如何限制'fscanf'字符串的字符數:'fscanf(pfile,「%99s」,stuff .imgloc)'? – 2013-02-14 12:46:04

+0

@Daniel Fischer:看起來fscanf和「%99s」確實可行。確保字符串緩衝區有一個額外的字節來保存終止的NULL。 (例如,「%99s」需要char buf [100]。)然後我會檢查是否有緩衝區溢出,例如'if(strlen(buf)== 99)...'。如果滿足這個條件,我會用錯誤消息中止程序而不是嘗試恢復,但這取決於應用程序。試圖恢復可能會變得棘手。 – 2013-02-14 19:09:23

0

我的猜測是,你還沒有建立一個緩衝區,以保持imgloc值,使用malloc或堆棧。

+1

在這個意義上什麼是堆棧指針? – 2013-02-14 12:19:39

+1

謝謝。我的意思是一個指向調用鏈中早些時候某個函數棧上緩衝區的指針。爲清晰起見進行編輯。 – Rumpsteak 2013-02-14 12:23:35

0

一個好主意 - 一般來說 - 是在開發應用程序時使用內存調試器(如valgrind)。

通過這種方式,您可以確保從一開始您的程序不會泄漏內存(稍後將進行調試的噩夢),並且您可以檢測到您不必訪問的讀取或寫入內存的內容(其中導致段錯誤,導致程序崩潰)。

在您的具體情況下,Valgrind會提醒您,您正在寫入一個您無權訪問的內存地址X(並且可能使用未初始化的內存),併爲您提供文件名和行號用調試信息編譯(-g)。在這種情況下,它會指出你fscanf - 所以你會仔細看看。如果通過查看該行無法找到問題,則可以將其分解爲逐個讀取參數,直到它(大概)將指向您分配字符串的行。

雖然這不會解決問題,如果你不知道char *沒有分配任何內存(除了保留指針的大小),它給你一個更好的主意從哪裏開始尋找。當然,現在你知道你需要保留內存,所以當你再次看到問題時,你會立即應用這些知識。