2014-01-11 68 views
0

我在C程序中有一個非常奇怪的問題,其中變量互相覆蓋。我有一個可變logFilePath其被這樣定義:在C覆蓋現有指針的字符串指針

logFilePath = pathToFile(logDirectory,argv[2]); 

功能pathToFile是這樣實現的。

char *pathToFile(char *directory, char *file) { 
    char *filePath = malloc(sizeof(*directory)+sizeof(*file)+10); 
    int i; 
    for (i = 0; directory[i] != '\0'; i++) { 
    if (directory[i+1] == '\0' && directory[i] != '/') strcat(directory,"/"); 
    } 
    strcat(filePath, directory); 
    strcat(filePath, file); 
    return filePath; 
} 

出於某種原因,logFilePath被完全不相關的函數修改。它被修改的功能就是這樣調用的

line = getIdentifierFromLine(line); 

並執行。

char *getIdentifierFromLine(char *line) { 
    char *ident = malloc(sizeof(char)*30); 
    int i = 0; 
    printf("%s\n", ident); 
    while (line[i] != ';') { 
    ident[i] = line[i]; 
    i++; 
    } 
    return ident; 
} 

問題是,logFilePaths片似乎是相同的身份證明,即前15個字符後的一半。將ident初始化爲logFileDirectory的前15個字符後的部分,並更改ident中每個char的值會更改logFileDirectory中的值。這裏是怎麼回事?

+4

'的sizeof(*目錄)'和'的sizeof(*文件)'意思'的sizeof(char)的' – BLUEPIXY

+0

我通過將pathToFile中的filePath的malloc更改爲sizeof(char)* 150'來解決此問題。我仍然不明白爲什麼我沒有得到分段錯誤? – stmfunk

+0

filePath不是「」。更改'strcat(filePath,目錄);'到'strcpy(filePath,directory);' – BLUEPIXY

回答

4

sizeof不做字符串長度檢查。此:

char *filePath = malloc(sizeof(*directory)+sizeof(*file)+10); 

是錯誤的。 sizeof(*directory)給出了字符的大小(通常是1)。

你想是什麼:

char *filePath = malloc(strlen(directory)+strlen(directory)+2); 

2個額外的就足夠了,一個可選的/,一個用於空終止字符。

因此,您不會爲文件路徑分配足夠的內存,導致未定義的行爲。在你的情況下,重寫緩衝區。這也可能導致段錯誤或其他奇怪的事情(我有一次有效的代碼段被遺漏,因爲我在其他地方犯了一個錯誤。)

+0

sizeof(* directory)給出了char的大小,而不是指向char的指針,所以可能是1 – Ervadac

+0

@Ervadac你是對的,我更新了我的答案。 –

+0

是的,sizeof(變量)比sizeof(type)imo更容易混淆。 – Ervadac

0

日誌的標準方法(以我的經驗)是使用stdout或stderr流。在C++中使用這些你需要包括的iostream,並且如下使用:

#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    using std::cout; 
    using std::cerr; 
    using std::endl; 

    cout << "Output message" << endl; 
    cerr << "Error message" << endl; 
} 

然而,這僅實現了印刷到這些輸出,其通常在一個終端而告終。如果你想使用這些標準的流方法(這是非常可讀的)輸出到一個文件,那麼你必須以某種方式重定向你的輸出。這樣做的一種方法是使用由cstdio提供的freopen函數。這樣做是打開一個文件,並將給定的流移動到該文件。看到這裏的文件。一個例子是:

#include <iostream> 
#include <cstdio> 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 
    freopen("output.txt", "w", stdout); 
    freopen("error.txt", "w", stderr); 

    cout << "Output message" << endl; 
    cerr << "Error message" << endl; 
} 
+1

什麼? ---------- – Duck

+0

OP是C語言,而不是C++。 – sqykly

+0

logFilePath不是應用程序日誌,它只是一個變量名稱。此外,應用程序使用C而不是C++。 – stmfunk

0

問題是在爲filePath分配空間時計算大小:

char *filePath = malloc(sizeof(*directory)+sizeof(*file)+10); 

這裏directorychar*類型,因此*directory具有類型charsizeof(*directory)1。對於sizeof(*file)也是如此,只有12個字節的內存被分配。

如果沒有足夠的空間,該路徑被寫入了緩衝區的結束,到後來結束在其他功能屬於ident空間。然後寫入*indent會修改filePath末尾佔用的內存。

而不是sizeof你應該使用strlen()確定輸入字符串的長度:

char *filePath = malloc(strlen(directory)+strlen(file)+10);