2011-02-11 79 views
0

這裏是一個wchar_t的*字符串轉換爲一個char *字符串的C代碼:致命錯誤*爲char *轉換

wchar_t *myXML = L"<test/>"; 
size_t length; 
char *charString; 
size_t i; 
length = wcslen(myXML); 
charString = (char *)malloc(length); 
wcstombs_s(&i, charString, length, myXML, length); 

代碼編譯,但在exectution在上次檢測到致命錯誤並停止運行。

現在,如果我替換這一個最後一行:

wcstombs_s(&i, charString, length+1, myXML, length); 

我剛添加+1到第三個參數。然後,它完美地工作...

爲什麼需要添加此技巧?或者我的代碼中有其他缺陷嗎?

+0

注意:`*`結尾是:`wchar_t *`和`char *`。 – 2011-02-11 10:35:50

+0

感謝您的精確。 – Dunaril 2011-02-11 10:37:58

+0

@Marcelo:這是一個品味和習慣的問題,並且有充足的理由像Dunaril那樣編寫它(例如`int * a,b;`表示`b`也是``int`的指針)。 – Thomas 2011-02-11 10:38:45

回答

2
DESCRIPTION 
     The wcslen() function is the wide-character 
     equivalent of the strlen(3) function. It determines 
     the length of the wide-character string pointed to by 
     s, not including the terminating L'\0' character. 

訣竅是,你應該總是認準形式的代碼:

string = malloc(len); 

非常懷疑,因爲這兩個wcslen(3)strlen(3)返回字符串長度沒有NUL字節malloc(3)必須分配空間那個字節。有時候有點吸吮。

因此,每當您看到string = malloc(len);而不是string = malloc(len+1);時,請仔細閱讀len如何分配。

char String = (char *)malloc(length + 1); 

應該做的伎倆。 :)

編輯

更好的是,請wcstombs()的大小首先分配:

size_t len = wcstombs(NULL,src,0) + 1; 
char *dest = malloc(len); 
len = wcstombs(dest, src, len); 
if (len == -1) /* handle error */ ... 

+1分配爲ASCII NUL,和wcstombs()將報告如何進行轉換需要很多內存。它會執行的兩次轉換,一次用於跟蹤所需的內存,然後一次用於存儲結果,但維護起來要簡單得多。第二次,當它存儲結果時,它將最多寫入len字節,包括字節數

4

對於'\0'終結符字符,您需要一個額外的字節。 wcslen不包括在它返回的長度!

要正確地做到這一點,你不只是需要通過length+1wcstombs_smalloc

charString = (char *)malloc(length+1); 
wcstombs_s(&i, charString, length+1, myXML, length); 

即使這樣,我懷疑這將無法正常工作。並非所有寬字符都可以映射到單個char,因此對於非ASCII字符,您需要多字節字符串中的額外空間。