Kri*_*hty 6 c++ winapi abi memory-alignment
我将 GUI 代码中的问题缩小到SetWindowTextW(HWND, wchar_t *)如果新窗口标题未与两个字节对齐则默默失败。在本例中,SetWindowText()返回1( success ) 但不设置新文本。
MSVC 上的自然对齐wchar_t是 2 个字节,所以这绝对是我的错误。但为了确保我尝试找到 Win32 字符串的对齐规则。
我没有找到官方文档,只是一个旧的新闻组帖子提到了 Open Watcom 编译器\xc2\xa0\xe2\x80\x93的错误报告,该报告声称Windows NT 上的 Win32 和 COM 实际上需要4 字节对齐!虽然这对我来说似乎很奇怪,但我注意到 MSVC 确实将每个wchar_t文字对齐到四个字节,而不是两个。实际上,您可以wchar_t通过 使 MSVC 更密集地打包常量字符串alignas(2)。Win32 中的堆粒度也 >=8 字节。
如果 Win32 需要对宽字符字符串进行四字节对齐(如源声明),并且 API 调用在错误的数据对齐上默默失败(如SetWindowText()1 字节对齐),我感觉遇到了很大的麻烦。
有没有官方文档说明 Win32/COM 中宽字符串的明确对齐要求?是两个字节还是四个字节?
\n重现问题的代码:
\n#include <Windows.h>\n#include <CommCtrl.h>\n#include <cassert>\n\nint main() {\n\n auto hWnd = CreateWindowW(WC_BUTTONW, L"original title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, nullptr, nullptr);\n assert(hWnd);\n ShowWindow(hWnd, SW_SHOWDEFAULT);\n UpdateWindow(hWnd);\n\n // Set title (aligned string):\n auto alignedResult = SetWindowTextW(hWnd, L"aligned title");\n assert(alignedResult != 0);\n\n // Set title (unaligned string):\n char buffer[50];\n memcpy(&buffer[1], L"unaligned title", sizeof L"unaligned title");\n auto unalignedResult = SetWindowTextW(hWnd, reinterpret_cast<wchar_t*>(&buffer[1])); // undefined behavior but for simplicity\n assert(unalignedResult != 0); // success is reported but title didn\xe2\x80\x99t change\n\n MSG msg;\n while (GetMessage(&msg, nullptr, 0, 0)) {\n TranslateMessage(&msg);\n DispatchMessage(&msg);\n }\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n
Win32 宽字符串对齐为两个字节。
使用 Windows 标头一文包含控制结构打包一节,该节将 Win32 类型对齐与 C 编译器的类型对齐联锁。这归结为宽字符字符串的两字节对齐。
问题中链接的讨论不适用,因为它是关于BSTRs 的。它们具有与宽字符串不同的内存布局。
问题SetWindowTextW()是我遇到了未指定的行为,因为我通过传递未对齐的数据违反了基本的 API 规则。
除了文档之外,您还可以在 Windows 标头中找到开创先例的位置。CHARFORMATW例如,该结构是四字节对齐的,但包含两字节对齐的宽字符字符串。
| 归档时间: |
|
| 查看次数: |
294 次 |
| 最近记录: |