2016-08-10 58 views
-1

我在我的Mac上編譯了代碼,GCC優化標記爲-O3以加速執行時間。這完美地工作在我的本地機器上,導致速度提高2/3。GCC優化:由fgets導致的錯誤

但是,我試圖編譯Amazon EC2上的代碼,因爲我正在處理大型數據集。使用-O3優化標誌導致以下警告

警告:調用與屬性警告聲明爲「__fgets_chk_warn」: 與fgets稱爲具有比目標緩衝區

的長度更大的尺寸在各自的功能,一個文本文件逐行解析。但是,我不明白爲什麼最終會發出警告。該函數的代碼如下:

int loadPriceData(const char *filename, double *target) { 
    char line[40]; 
    FILE *fp; 
    fp = fopen(filename, "r"); 
    if (fp == NULL) { 
     return -1; 
    } 
    int i = 0; 
    while (fgets(line, 80, fp) != NULL) { 
     sscanf(line, "%lf\n", target + i); 
     i += 1; 
    } 
    fclose(fp); 
    return i; // Return number of elements 
} 

target是指向與10000元素默認的陣列。輸入的數量不是預先知道的,而是由函數返回的。

+8

'40 <80'。似乎不太神祕。 – EOF

+0

問題是該行是一個40字節的數組,但您可以說它有80個字節。使用sizeof(行)而不是80. –

+0

讓我們擴展警告:'fgets調用比目標緩衝區長度(這是40)更大的尺寸(這是80)' – alk

回答

3

您的確在呼叫fgets(line, 80, fp),但目標數組line被定義爲字符數40。 Amazon EC2上的編譯器配置得更好或者比您的更智能。如果文件包含超過39個字節的行,這是一個真正的bug。

順便提一下,在Mac上調用爲gcc的編譯器通常是clang的實例。嘗試gcc --version

請注意,您的程序不會檢查是否讀取了太多數據,也不會檢測轉換是否成功。兩者都導致未定義的行爲。

下面是一個更安全的版本:

int loadPriceData(const char *filename, double *target, int nb_items) { 
    char line[80]; 
    FILE *fp = fopen(filename, "r"); 
    if (fp == NULL) { 
     return -1; 
    } 
    int i = 0; 
    while (fgets(line, sizeof line, fp) != NULL) { 
     if (i < nb_items) { 
      if (sscanf(line, "%lf", target + i) != 1) 
       target[i] = 0; 
     } 
     i += 1; 
    } 
    fclose(fp); 
    return i; // Return number of elements 
}