Debugging 如何使用Visual Studio调试amd64上未对齐的访问?

Debugging 如何使用Visual Studio调试amd64上未对齐的访问?,debugging,visual-c++,assembly,64-bit,alignment,Debugging,Visual C++,Assembly,64 Bit,Alignment,我想调试和分析一些执行未对齐访问的64位软件,如以下示例所示: int foo[2] = { 1, 2 }; *((int *)((char *)foo + 2)) = 3; gcc方式 在使用gcc和gdb时,我知道两种方法。第一种是通过在C++代码> EFLASS登记器中启用对齐检查位(位18),直接在C或C++代码中: asm volatile("pushf \n" "pop %%rax \n" "or $0x40000, %%rax

我想调试和分析一些执行未对齐访问的64位软件,如以下示例所示:

int foo[2] = { 1, 2 };
*((int *)((char *)foo + 2)) = 3;
gcc方式 在使用gccgdb时,我知道两种方法。第一种是通过在C++代码> EFLASS<代码>登记器中启用对齐检查位(位18),直接在C或C++代码中:

asm volatile("pushf \n"
             "pop %%rax \n"
             "or $0x40000, %%rax \n"
             "push %%rax \n"
             "popf \n" ::: "rax");
这非常方便,因为我可以在应用程序内部选择是否绕过未对齐的访问检查,例如在调用已知的错误库时

另一种方法是在调试可执行文件的任何时刻从gdb

set $eflags |= 1<<18

set$eflags |=1使用asmjit

一个非常麻烦的解决方法是在程序中有一个线程不断地设置这个位。大约每100毫秒


然后您将知道,在从断点恢复后不久,将再次检查对齐。虽然不是100%安全,但可能已经足够好了

不幸的是,在VS中调试x64调试器时,会清除任何异常的对齐检查标志(包括首先抛出以单步进入调试器的异常)。您是否尝试过使用windbg(一种功能更强大的windows调试器)单步执行代码?我还不能尝试使用AC标志,但使用r efl=或直接从寄存器窗口使用它应该很简单。
如果您没有安装windbg,您可以从最新的Windows SDK获得它。

听起来像是一个bug,所有的寄存器值都应该保存并还原。考虑提交一个bug报告:看起来链接被破坏了,现在是:“现实世界的Windows开发人员如何跟踪代码中的未对齐访问?”作为一名主要的Windows开发人员,我认为他们永远不会这样做,除非代码必须在安腾上运行。如果它必须在安腾上运行,异常将告诉位置。x86上未对齐访问的实际开销是多少?顺便说一句,您仍然可以在x64的.asm文件中使用程序集,但不能使用内联程序集。@Tim:谢谢您的提示,我将提交一份报告@弗拉迪斯拉夫:我计划写一篇关于这个问题的综合基准的文章;在严重的情况下,我看到在重新调整数据时,性能提高了400%,但通常低于10%。但通常值得调查。错误报告。目前他们似乎无法重现这个问题,但我认为我提供了足够的额外信息让他们重现。通常,未对齐访问的成本只是,如果它跨越缓存线边界,则必须从内存中提取两条缓存线,而不是一条。在x86上,成本通常可以忽略不计。在其他平台上,它可能更重要(或者可能只会导致一个错误),我不明白-这将如何帮助检测未对齐的访问?看起来这可能是一种编译标志更改的方法,但Sam已经在MSVC和GCC中找到了解决方案。与我所寻找的内容没有太大关系,但无论如何,感谢您让我知道这个有趣的项目@山姆:你可以用
SuspendThread
GetThreadContext
,和
SetThreadContext
进行疯狂的破解来设置另一个线程的EFLAGS。但请不要发布这样的生产代码。感谢您指出VS实际上无法完成这项工作,并建议使用windbg。我已经在Linux上调试了这个应用程序,但是下次我一定会尝试windbg。
#include <intrin.h>
/* ... */
__writeeflags(__readeflags() | 0x40000);