Visual c++ unicode和框架的深不可测的问题

Visual c++ unicode和框架的深不可测的问题,visual-c++,gcc,unicode,frameworks,wchar-t,Visual C++,Gcc,Unicode,Frameworks,Wchar T,我遇到了一个非常奇怪的问题。。。如果将以下琐碎的测试代码注入单个cococoa应用程序,那么它将正常工作,但当我在我的一个框架中使用它时,我会得到完全出乎意料的结果 wchar_t Buf[2048]; wcscpy(Buf, L"/zbxbxklbvasyfiogkhgfdbxbx/bxkfiorjhsdfohdf/xbxasdoipppwejngfd/gjfdhjgfdfdjkg.sdfsdsrtlrt.ljlg/fghlfg"); int len1 = wcslen(L"/zbxbxklb

我遇到了一个非常奇怪的问题。。。如果将以下琐碎的测试代码注入单个cococoa应用程序,那么它将正常工作,但当我在我的一个框架中使用它时,我会得到完全出乎意料的结果

wchar_t Buf[2048];
wcscpy(Buf, L"/zbxbxklbvasyfiogkhgfdbxbx/bxkfiorjhsdfohdf/xbxasdoipppwejngfd/gjfdhjgfdfdjkg.sdfsdsrtlrt.ljlg/fghlfg");
int len1 = wcslen(L"/zbxbxklbvasyfiogkhgfdbxbx/bxkfiorjhsdfohdf/xbxasdoipppwejngfd/gjfdhjgfdfdjkg.sdfsdsrtlrt.ljlg/fghlfg");
int len2 = wcslen(Buf);

char Buf2[2048];
Buf2[0]=0;
wcstombs(Buf2, Buf, 2048);

// ??? Buf2 == ""
// ??? len1 == len2 == 57, but should be 101

这怎么可能,我疯了吗?即使内存损坏,也不可能损坏堆栈上分配的所有这些值。。。为什么连wcslen(L“MyWideString”)都不能工作?更改测试字符串会更改其长度,但它总是错误的,wcstombs返回-1

setlocale()不在任何地方使用,测试字符串只包含ASCII字符,为了便于移植,我使用了-fshort-wchar编译器选项,但它在测试应用程序中运行良好


请帮忙

C/C++中的宽字符实现可以是任何内容,包括1字节、2字节或4字节。这取决于编译器和编译到的平台

也许维基百科不是引述的最佳场所,但在这种情况下: 声明

。。。wchar_t的宽度是特定于编译器的,可以小到8位

。。。由于历史兼容性原因,C90下的宽字符应为16位值。符合1064—1:2000 Unicode标准的C和C++编译器一般假定32位值……/P>
因此,不要假设并使用
sizeof(wchar\u t)
我刚刚用GCC4.6再次测试了这一点。在标准设置中,这与预期一样有效,所有长度都为101。但是,使用您的选项
-fshort wchar
我也会得到意外的结果(在我的例子中是51,在使用setlocale()后的最终转换是251)

因此,我在man条目中查找选项:

警告,-fshort wchar开关导致GCC生成的代码与未使用该开关生成的代码不兼容。使用它符合非默认应用程序二进制接口


我想这就解释了:当您链接到标准库时,您需要使用正确的ABI和类型约定,您将使用该选项覆盖这些约定。

-fshort wchar
更改编译器的ABI,因此您需要使用wchar\t重新编译glibc、libgcc和所有库。否则,glibc中的wcslen和其他函数仍然假定wchar_t为4字节


请参阅:

如果宽字符串的长度大于101字节,我可以理解,但它怎么会小于???好吧,从外观上看,问题是由-fshort wchar引起的,根据谷歌的说法,它导致宽字符串例程的工作不正确。。。但是我仍然不明白,为什么wcscpy()和wcslen()在一个单独的测试应用程序中工作得非常好……这不可编译,什么是
WBUF
?您应该始终调用
setlocale(LC_CTYPE,”)wcstombs
mbstowcs
之前使用code>或同等产品。我刚刚在Linux中运行了您的代码,得到了len1和len2的101,这是
wcstombs
调用和
strlen(Buf2)的结果.WBUF是一个错误,已修复。Kernek,谢谢你的宝贵意见,你能告诉我,在应用程序的入口点调用setlocale()是否合适吗?我应该在应用程序终止时恢复以前的区域设置吗?好吧,在我的情况下,问题与sizeof(wchar_t)无关,因为它总是2,我使用相同的编译器和强制32位模式。无论如何,我不会使用任何转换为MBS的东西,因为它依赖于操作系统配置,特别是因为它可能会失败。我甚至会说MBS已经过时了。