64位MASM中sscanf在Win10/11返回0问题排查求助
MASM64 SDK中sscanf返回0问题的排查与解决
问题现象
- 调用sscanf的代码在Windows 7运行正常,Windows 10/11下返回0;
- 代码在原项目中可正常运行,迁移到新项目后sscanf返回0;
- 原本正常的代码运行一段时间后,也出现sscanf返回0的情况。
核心排查与修复方案
1. 64位Windows栈对齐要求未满足
64位Windows调用约定强制要求调用函数前栈必须是16字节对齐。你的第一段代码中sub rsp, 30h(分配48字节栈空间),加上push rbp的8字节,栈指针偏移量为56字节,并非16的整数倍。这种未对齐的栈在Windows 7中可能兼容,但Windows 10/11的严格栈检查会导致sscanf调用失败。
修复:调整栈空间为16的倍数,例如将sub rsp, 30h改为sub rsp, 38h(分配56字节,加上rbp的8字节总偏移64,为16*4),确保调用sscanf前rsp符合对齐要求。
2. MASM64 SDK invoke宏的参数处理问题
第三方invoke宏可能存在参数传递或栈处理的bug,比如未正确维护寄存器参数、未自动处理栈对齐。
验证与修复:暂时替换invoke为手动call调用,测试是否正常:
mov rcx, offset buffer mov rdx, offset fmt1 mov r8, offset temp call sscanf
如果手动call正常,说明invoke宏存在问题,需检查宏定义,或直接改用手动调用方式。
3. 字符串终止符缺失或内存污染
- 第二段代码中
GetDlgItemTextA获取的字符串可能因长度超限导致0终止符丢失,sscanf无法识别有效格式; - 数据段变量(如
buffer、temp)可能被意外覆盖,导致解析失败。
修复:
- 在
GetDlgItemTextA后手动添加0终止符:
lea r8, buffer invoke GetDlgItemTextA,,ID_TXT1,,size_of_buffer or eax,eax jz wmBYE mov byte ptr [r8+eax], 0 ; 强制添加字符串终止符
- 检查数据段变量布局,避免地址重叠或未初始化的内存污染。
4. 运行时库与Locale差异
Windows 10/11的msvcrt.dll版本与Win7不同,sscanf的浮点数解析可能受系统Locale影响(比如部分Locale用逗号作为小数点分隔符)。
修复:显式设置C Locale,避免解析行为变化:
invoke setlocale, LC_ALL, offset locale_c .data locale_c db "C", 0
5. 栈帧未正确恢复导致内存泄漏
第一段代码中建立栈帧后,返回前未恢复rsp到rbp,直接ret会导致栈空间泄漏,长期运行后栈资源耗尽,引发后续调用失败。
修复:返回前恢复栈帧:
mov rsp, rbp pop rbp ret
修复后的第一段代码示例
.code main proc push rbp mov rbp, rsp sub rsp, 38h ; 保证16字节对齐的栈空间 mov rcx, offset buffer mov rdx, offset fmt1 mov r8, offset temp invoke sscanf movq xmm0, temp mov rsp, rbp ; 恢复栈帧 pop rbp ret main endp .data fmt1 db "%lf", 0 temp dq ? buffer db "3.14159264", 0 end
内容的提问来源于stack exchange,提问作者mantissa
相关产品推荐
相关产品推荐

