【问题标题】:wcslen() returns incorrect result when pragma pack used使用 pragma pack 时 wcslen() 返回不正确的结果
【发布时间】:2020-02-18 22:54:03
【问题描述】:

我发现当源是 wchar_t 数组、打包结构的成员时,wcslen() 在 gcc 上返回不正确的结果(并且在 msvc 上正确)。我知道在 linux sizeof(wchar_t) == 4 和 windows 上它的 2 但仍然无法理解打包如何影响 wcslen() 函数。如果我将 wchar_t/wcslen 更改为 char/strlen 它会按预期工作。

#include <cstdint>
#include <cwchar>
#include <cstring>

#pragma pack(push, 1)

struct A
{
    uint8_t c;
};

struct B
{
    A  a;
    wchar_t buf[9];
};

#pragma pack(pop)


int main()
{
    const wchar_t* s = L"05.00.06";
    B b{};
    memcpy(b.buf, s, wcslen(s) * sizeof(wchar_t));

    return wcslen(b.buf);
}

为什么用 gcc 编译的这段代码返回 7?它应该返回 8(就像 msvc 一样)。顺便说一句,复制的字节是正确的(b.buf[7] == '6')。

【问题讨论】:

标签: c++ gcc visual-c++ wchar-t pragma-pack


【解决方案1】:

此代码的行为未定义且不可预测。您正在向 wcslen 函数传递一个无效指针,因为它不一定满足其类型的对齐要求。

可能在您的平台上,wchar_t 的对齐要求是 2。因此,您传递给 wcslen 的指针无效。您看不到与 strlen 类似的行为,因为在这种情况下对齐要求是 1,这意味着根本没有要求。

除非您知道自己已遵守平台的对齐要求,否则请勿对打包结构进行操作。否则,结果是完全不可预测的。在许多平台上,您的代码都会崩溃。

【讨论】:

  • 知道了,谢谢。 sizeof(A) == 1, sizeof(wchat_t) == 4 所以编译器会在 A 之后插入 3 个字节的填充以使 buf 地址与 sizeof(wchat_t) 对齐,但 pragma pack 会阻止填充并且地址未对齐。
猜你喜欢
  • 2011-06-21
  • 2012-04-11
  • 2016-02-06
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
相关资源
最近更新 更多