2014-08-30 51 views
1

我在使用這段代碼的麻煩:調用strtok()時訪問衝突; C++

char KernelFS::doesExist(char* fname){ 
    char part; 
    char name[8]; 
    char ext[3]; 

    char* token; 

    token = strtok(fname, "\\"); 
    strncpy(&part, token, 1); 

    token = strtok(fname, "\\"); 
    strncpy(name, token, 8); 

    token = strtok(fname, "\\"); 
    strncpy(ext, token, 3); 

    return 0; 
} 

它編譯和休息,當我在strtok的第一次調用(...)運行它 - 訪問衝突寫入位置... 無知道爲什麼:(

我稱這個功能:

KernelFS :: doesExist( 「X:\ TEST.EXE」);

點是將FNAME char數組分成3個陣列; 一分區的名稱, 一個用於文件名, 一個用於文件擴展名;

感謝您的幫助! :)

+1

爲什麼當你有'std :: string'時,你使用原始字符數組。 – 101010 2014-08-30 12:26:38

+0

填充後絕不會使用'part','name','ext'。如果修改代碼以使用它們,請記住它們不是字符串(您已經創建了沒有空終止符的char緩衝區) – 2014-08-30 12:35:52

+0

還有一件事:'\ t'具有特殊含義,如果你想要一個單獨的分隔符,那麼就使用'X:\\ test.exe' – 2014-08-30 12:37:40

回答

4

在您的例子:

KernelFS::doesExist("X:\test.exe"); 

"X:\test.exe"處於const char*類型的事實,你不能修改它。原始字符串文字被分配在受保護的內存區域中,因此遇到了錯誤。

字符* strtok字符* STR,常量字符*定界符);

str - 請注意,該字符串是修改爲通過被分成更小的字符串(令牌)。可選地,可以指定一個空指針,在這種情況下,該函數繼續掃描以前成功調用函數的地方結束。

如果你真的想使用<cstring>庫(不建議雖然),你倒是應該在棧上分配的字符串,而不是從程序符號區域收購它的。

char path[] = { "X:\\test.exe" }; 
KernelFS::doesExist(path); 

但是,建議您切換到<string>庫。

+0

。完成。謝謝。 – Alek988Alek 2014-08-30 12:30:05

+0

你也應該檢查'KernelFS :: doesExist()'沒有收到'NULL'指針,並且'strtok()'不返回NULL。 – HRold 2014-08-30 12:30:39

+2

+1,@ Alek988Alek然後,密切關注如果擴展名爲3個字符寬,'strncpy'將不會用nullchar終止您的文件擴展名。你的緩衝區似乎都是1個字符短的。 – WhozCraig 2014-08-30 12:31:40

1

我建議作以下修改:

char KernelFS::doesExist(char* fname) 
{ 
    // Our variables. 
    char part[2]; 
    char name[9]; 
    char ext[4];   
    char* token; 

    // Initialize variables. 
    memset(part, '\0', 2); 
    memset(name, '\0', 9); 
    memset(ext, '\0', 4); 

    // If we receive an invalid string: 
    if (fname == NULL) 
     return -1; // Return error. 

    // Process. 
    if ((token = strtok(fname, "\\")) != NULL) 
     strncpy(part, token, 1); 
    if ((token = strtok(fname, "\\")) != NULL) 
     strncpy(name, token, 8); 
    if ((token = strtok(fname, "\\")) != NULL) 
     strncpy(ext, token, 3); 

    // If we retrieved the 3 variables: 
    if (strlen(part) > 0 && strlen(name) > 0 && strlen(ext) > 0) 
    { 
     // Do something with part, name and ext here. 
    } 

    // Return success. 
    return 0; 
} 

正如彼得·S.說,要注意調用這個函數有一個有效的char *(不是const char *或其他任何東西)。