wchar_t *到char *转换的致命错误

时间:2011-02-11 10:32:15

标签: c string

这是一个将wchar_t *字符串转换为char *字符串的C代码:

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。然后它完美地工作......

为什么需要添加这个技巧?或者我的代码中的其他地方是否有缺陷?

2 个答案:

答案 0 :(得分:4)

'\0'终止符需要一个额外的字节。 wcslen在返回的长度中不包含此内容!

要做到这一点,您不仅需要将length+1传递给wcstombs_s,还需要传递给malloc

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

即便如此,我怀疑它无法正常工作。并非所有宽字符都可以映射到单个char,因此对于非ASCII字符,您将需要多字节字符串中的额外空间。

答案 1 :(得分: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)必须使用该字节分配空间。 C有时候很糟糕。

因此,每当您看到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个字节,包括ascii nul