glibc wcslen() 是否期望数据沿 wchar_t 大小的边界对齐?
Does glibc wcslen() expect data alignment along wchar_t sized boundaries?
为了这个我已经绞尽脑汁好几个小时了。 glibc wcslen()
返回的值与给定输入字符串的预期值不同。我已经将问题缩小到可能的数据对齐问题,但即使那样对我来说也没有意义。我自己的转储字符串的函数似乎工作正常并且计算的大小类似于 wcslen()
应该如何工作。
#ifndef WCHAR
#define WCHAR wchar_t
#endif
...
void DumpWCStr(const WCHAR *str)
{
size_t len = 0, len2 = wcslen(str);
while (*str != L'[=11=]')
{
printf("%lu %lc\n", (size_t)*str, *str);
str++;
len++;
}
printf("Size: %lu (wcslen: %lu)\n", len, len2);
}
void TestFunc()
{
char *prebuffer = (char *)malloc(100 * sizeof(WCHAR) + 1);
WCHAR *tempbuffer = (WCHAR *)(prebuffer + 1);
WCHAR tempbuffer2[100];
memset(prebuffer, 0xFF, 100 * sizeof(WCHAR) + 1);
swprintf(tempbuffer, 100, L"%ls (%d)", L"test", 15);
DumpWCStr(tempbuffer);
memset(prebuffer, 0xFF, 100 * sizeof(WCHAR) + 1);
tempbuffer = (WCHAR *)prebuffer;
swprintf(tempbuffer, 100, L"%ls (%d)", L"test", 15);
DumpWCStr(tempbuffer);
memset(prebuffer, 0xFF, 100 * sizeof(WCHAR) + 1);
swprintf(tempbuffer2, 100, L"%ls (%d)", L"test", 15);
DumpWCStr(tempbuffer2);
}
输出:
116 t
101 e
115 s
116 t
32
40 (
49 1
53 5
41 )
Size: 9 (wcslen: 8)
116 t
101 e
115 s
116 t
32
40 (
49 1
53 5
41 )
Size: 9 (wcslen: 9)
116 t
101 e
115 s
116 t
32
40 (
49 1
53 5
41 )
Size: 9 (wcslen: 9)
here 中的 glibc wcslen() 实现显示 wcslen() 实现为:
size_t
__wcslen (const wchar_t *s)
{
size_t len = 0;
while (s[len] != L'[=13=]')
{
if (s[++len] == L'[=13=]')
return len;
if (s[++len] == L'[=13=]')
return len;
if (s[++len] == L'[=13=]')
return len;
++len;
}
return len;
}
在第一个 swprintf()
之后尝试 printf("%ls\n", tempbuffer);
结果:
wcsrtombs.c:94: __wcsrtombs: Assertion `data.__outbuf[-1] == '[=14=]'' failed.
这可能是因为 __wcslen()
在 __wcsrtombs()
中返回 8 而不是 9。
我正在将代码编译为 C++,目标是英特尔 x86/x64。
glibc wcslen() 是否期望数据在 wchar_t 大小的边界上对齐?这不是我阅读 wcslen() 源代码的方式,但它确实表现得像它期望数据对齐。
一般来说,C++ 总是要求对对象的所有访问至少与类型要求的边界对齐。这是因为对象不能存在于未对齐的地址中。因此,此要求并非特定于 wcslen
.
在您的系统上,alignof(wchar_t)
可能大于 1,在这种情况下 prebuffer + 1
总是未对齐,因此不能包含 wchar_t
对象。
违反此要求会导致未定义的行为。
为了这个我已经绞尽脑汁好几个小时了。 glibc wcslen()
返回的值与给定输入字符串的预期值不同。我已经将问题缩小到可能的数据对齐问题,但即使那样对我来说也没有意义。我自己的转储字符串的函数似乎工作正常并且计算的大小类似于 wcslen()
应该如何工作。
#ifndef WCHAR
#define WCHAR wchar_t
#endif
...
void DumpWCStr(const WCHAR *str)
{
size_t len = 0, len2 = wcslen(str);
while (*str != L'[=11=]')
{
printf("%lu %lc\n", (size_t)*str, *str);
str++;
len++;
}
printf("Size: %lu (wcslen: %lu)\n", len, len2);
}
void TestFunc()
{
char *prebuffer = (char *)malloc(100 * sizeof(WCHAR) + 1);
WCHAR *tempbuffer = (WCHAR *)(prebuffer + 1);
WCHAR tempbuffer2[100];
memset(prebuffer, 0xFF, 100 * sizeof(WCHAR) + 1);
swprintf(tempbuffer, 100, L"%ls (%d)", L"test", 15);
DumpWCStr(tempbuffer);
memset(prebuffer, 0xFF, 100 * sizeof(WCHAR) + 1);
tempbuffer = (WCHAR *)prebuffer;
swprintf(tempbuffer, 100, L"%ls (%d)", L"test", 15);
DumpWCStr(tempbuffer);
memset(prebuffer, 0xFF, 100 * sizeof(WCHAR) + 1);
swprintf(tempbuffer2, 100, L"%ls (%d)", L"test", 15);
DumpWCStr(tempbuffer2);
}
输出:
116 t
101 e
115 s
116 t
32
40 (
49 1
53 5
41 )
Size: 9 (wcslen: 8)
116 t
101 e
115 s
116 t
32
40 (
49 1
53 5
41 )
Size: 9 (wcslen: 9)
116 t
101 e
115 s
116 t
32
40 (
49 1
53 5
41 )
Size: 9 (wcslen: 9)
here 中的 glibc wcslen() 实现显示 wcslen() 实现为:
size_t
__wcslen (const wchar_t *s)
{
size_t len = 0;
while (s[len] != L'[=13=]')
{
if (s[++len] == L'[=13=]')
return len;
if (s[++len] == L'[=13=]')
return len;
if (s[++len] == L'[=13=]')
return len;
++len;
}
return len;
}
在第一个 swprintf()
之后尝试 printf("%ls\n", tempbuffer);
结果:
wcsrtombs.c:94: __wcsrtombs: Assertion `data.__outbuf[-1] == '[=14=]'' failed.
这可能是因为 __wcslen()
在 __wcsrtombs()
中返回 8 而不是 9。
我正在将代码编译为 C++,目标是英特尔 x86/x64。
glibc wcslen() 是否期望数据在 wchar_t 大小的边界上对齐?这不是我阅读 wcslen() 源代码的方式,但它确实表现得像它期望数据对齐。
一般来说,C++ 总是要求对对象的所有访问至少与类型要求的边界对齐。这是因为对象不能存在于未对齐的地址中。因此,此要求并非特定于 wcslen
.
在您的系统上,alignof(wchar_t)
可能大于 1,在这种情况下 prebuffer + 1
总是未对齐,因此不能包含 wchar_t
对象。
违反此要求会导致未定义的行为。