GetDateFormatEx返回非零值但输出缓冲区内容异常求助排查
日期格式化异常问题排查
问题现象
sprintf_s返回的cursize值为429496729(实际为int类型错误值的无符号表示)- 程序最终输出仅为
ts=06:21:20,currDateStr未生成有效日期字符串 - 所有Windows API(包括
GetDateFormatEx)均返回非零值,无报错信息
异常程序代码
#include <windows.h> #include <iostream> uint64_t shimTime(void) { FILETIME ts; GetSystemTimeAsFileTime(&ts); ULONGLONG systime = ((ULARGE_INTEGER*)&ts)->QuadPart; return systime; } int main() { static const size_t sz = 64; TCHAR currTimeStr[sz]; TCHAR currDateStr[sz]; FILETIME ts; int ret = -1; // Get current-time in pretty-format GetSystemTimeAsFileTime(&ts); uint64_t currTime = shimTime(); SYSTEMTIME stime, lstime; if (currTime == 0) { printf("currTime is 0\n"); swprintf_s(currTimeStr, sz, L"0"); swprintf_s(currDateStr, sz, L"0"); } else { if (!FileTimeToSystemTime((FILETIME*)&currTime, &stime)) { printf("Unable to get FileTimeToSystemTime, err=%u\n", GetLastError()); } if (!SystemTimeToTzSpecificLocalTime(NULL, &stime, &lstime)) { printf("Unable to get SystemTimeToTzSpecificLocalTime, err=%u\n", GetLastError()); } ret = GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &lstime, NULL, currTimeStr, _countof(currTimeStr)); printf("GetTimeFormatEx ret = %d\n", ret); if (!ret) { printf("GetTimeFormatEx failed, err=%u\n", GetLastError()); } ret = GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &lstime, L"ddd',' MMM dd',' yyyy", currDateStr, _countof(currDateStr), NULL); printf("GetDateFormatEx ret = %d\n", ret); if (!ret) { printf("GetDateFormatEx failed, err=%u\n", GetLastError()); } } currTimeStr[sz - 1] = '\0'; currDateStr[sz - 1] = '\0'; // Print time and date printf("Current time is: %S\n", currTimeStr); printf("Current date is: %S\n", currDateStr); char cp[1024]; int cursize = sprintf_s(&cp[0], 1023, "ts=%S %S", currTimeStr, currDateStr); if (cursize < 0 || cursize >= 1023) { printf("Error occurred during sprintf_s, cursize: %u\n", cursize); } printf("%s\n", cp); return 0; }
系统环境信息
C:\>systeminfo Host Name: MIGNT006 OS Name: Microsoft Windows Server 2019 Standard OS Version: 10.0.17763 N/A Build 17763 OS Manufacturer: Microsoft Corporation OS Configuration: Member Server OS Build Type: Multiprocessor Free Registered Owner: Flex Registered Organization: Flex Product ID: 00429-70000-00000-AA322 Original Install Date: 01/30/2021, 17:11:12 System Boot Time: 01/19/2024, 14:52:23 System Manufacturer: HP System Model: ProLiant DL360 G7 System Type: x64-based PC Processor(s): 2 Processor(s) Installed. [01]: Intel64 Family 6 Model 44 Stepping 2 GenuineIntel ~177 Mhz [02]: Intel64 Family 6 Model 44 Stepping 2 GenuineIntel ~177 Mhz BIOS Version: HP P68, 05/21/2018 Windows Directory: C:\WINDOWS System Directory: C:\WINDOWS\system32 Boot Device: \Device\HarddiskVolume1 System Locale: en-us;English (United States) Input Locale: en-us;English (United States) Time Zone: (UTC+02:00) Jerusalem Total Physical Memory: 16,374 MB Available Physical Memory: 5,051 MB Virtual Memory: Max Size: 18,806 MB Virtual Memory: Available: 7,398 MB Virtual Memory: In Use: 11,408 MB Page File Location(s): C:\pagefile.sys Domain: europe.ad.flextronics.com Logon Server: \\EUMIG002 Hotfix(s): 31 Hotfix(s) Installed. [01]: KB5033911 [02]: KB4486153 [03]: KB4535680 [04]: KB4549947 [05]: KB4561600 [06]: KB4562562 [07]: KB4589208 [08]: KB4598480 [09]: KB4601393 [10]: KB5000859 [11]: KB5003243 [12]: KB5003711 [13]: KB5005112 [14]: KB5034127 [15]: KB5006754 [16]: KB5008287 [17]: KB5009642 [18]: KB5011574 [19]: KB5012675 [20]: KB5014031 [21]: KB5014797 [22]: KB5015896 [23]: KB5017400 [24]: KB5020374 [25]: KB5023789 [26]: KB5028316 [27]: KB5030505 [28]: KB5031589 [29]: KB5032306 [30]: KB5034863 [31]: KB5005701 Network Card(s): 4 NIC(s) Installed. [01]: HP NC382i DP Multifunction Gigabit Server Adapter Connection Name: Ethernet 3 Status: Media disconnected [02]: HP NC382i DP Multifunction Gigabit Server Adapter Connection Name: Ethernet 4 DHCP Enabled: No IP address(es) [01]: 10.229.8.6 [03]: HP NC382i DP Multifunction Gigabit Server Adapter Connection Name: Ethernet 2 Status: Media disconnected [04]: HP NC382i DP Multifunction Gigabit Server Adapter Connection Name: Ethernet Status: Media disconnected Hyper-V Requirements: VM Monitor Mode Extensions: Yes Virtualization Enabled In Firmware: Yes Second Level Address Translation: Yes Data Execution Prevention Available: Yes
可能的原因分析
1. 字符串数组未初始化,存在随机内存值干扰
代码仅在currTime == 0的分支下初始化currDateStr,正常路径下数组未被初始化,内存中为随机值。即使GetDateFormatEx返回成功,若因区域数据异常等原因未正确写入完整字符串,currDateStr中残留的随机值会导致sprintf_s转换宽字符时失败。
2. 区域设置与时区的兼容性问题
系统区域为en-us,但时区设置为耶路撒冷(UTC+02:00),可能存在区域数据缺失或损坏,导致GetDateFormatEx无法按指定格式生成有效字符串。虽然API返回非零,但实际写入的内容可能为空或不完整。
3. sprintf_s的%S格式符转换失败
%S用于将宽字符转换为多字节字符,若currDateStr中包含无效宽字符(未初始化的随机值),sprintf_s会转换失败并返回-1(对应无符号显示为4294967295,可能日志记录存在笔误),此时输出会截断到转换失败前的位置,仅保留时间部分。
4. 手动设置终止符的潜在问题
代码末尾强制设置currDateStr[sz-1] = '\0',若GetDateFormatEx写入的字符串刚好占满sz-1个字符,原本自动添加的终止符会被覆盖。不过此场景下缓冲区足够大(格式字符串生成的日期长度远小于64),该问题概率较低,但仍可能影响字符串完整性。
排查建议
- 初始化字符串数组:在代码开头添加
memset(currDateStr, 0, sizeof(currDateStr)),避免随机内存值干扰。 - 验证时间转换正确性:添加代码打印
stime和lstime的各个字段(年、月、日、时、分、秒),确认时间转换链是否正常。 - 指定明确区域:将
LOCALE_NAME_USER_DEFAULT替换为具体区域名称(如L"en-US"),测试是否能正常生成日期。 - 检查系统文件完整性:运行
sfc /scannow命令,检查并修复可能损坏的系统区域数据文件。 - 获取
sprintf_s错误详情:在sprintf_s失败后调用GetLastError(),获取具体错误码以定位转换失败原因。
内容的提问来源于stack exchange,提问作者Shivangi Gupta
相关产品推荐
相关产品推荐

