为何使用_ui64tow_s替代_ui64tow后无法正常工作?
问题分析与修复方案
你遇到的问题核心在于**_ui64tow和_ui64tow_s的返回值逻辑完全不同**,直接替换后条件判断搞反了,导致原本应该执行的成功分支根本没走进去。
关键差异点
- 旧函数
_ui64tow:转换成功时返回目标缓冲区的指针(非NULL),失败返回NULL。所以原来的if (_ui64tow(...))是判断转换成功。 - 安全函数
_ui64tow_s:转换成功时返回0,失败返回非零的错误码(比如EINVAL表示参数无效,ERANGE表示数字太长装不下)。你现在写的if (_ui64tow_s(...))相当于只有转换失败才会进入分支,完全和预期逻辑相反!
修正后的代码
只需要把_ui64tow_s的判断条件改成等于0即可,同时你的缓冲区大小计算sizeof(wsz)/sizeof(WCHAR)是正确的(因为wsz是栈上数组,这样能准确拿到字符数上限):
#define PERCENT_SHIFT 10000000 #define SHORTSTRLEN 32 TCHAR g_szZero[SHORTSTRLEN] = TEXT("0"); // 假设g_szDecimal是预先定义的全局变量,比如TCHAR g_szDecimal[] = TEXT("."); WCHAR* PerfGraph::FloatToString(ULONGLONG ullValue, WCHAR* psz, BOOLEAN bDisplayDec) { ULONGLONG ulDecimal = 0; ULONGLONG ulNumber = 0; WCHAR wsz[100]; // 获取数字的整数部分: ulNumber = ullValue / PERCENT_SHIFT; // 修正:判断_ui64tow_s返回0表示转换成功 if (_ui64tow_s(ulNumber, wsz, sizeof(wsz) / sizeof(WCHAR), 10) == 0) { lstrcpy(psz, wsz); if (ulNumber) { ullValue = ullValue - ulNumber * PERCENT_SHIFT; } if (!ulNumber || bDisplayDec) { ulDecimal = ullValue * 100 / PERCENT_SHIFT; // 同样修正这里的判断条件 if (ulDecimal && _ui64tow_s(ulDecimal, wsz, sizeof(wsz) / sizeof(WCHAR), 10) == 0) { lstrcat(psz, g_szDecimal); if (ulDecimal < 10) lstrcat(psz, g_szZero); if (wsz[1] == L'0') wsz[1] = L'\0'; lstrcat(psz, wsz); } } } return psz; }
额外优化建议
为了让代码更安全,建议把lstrcpy和lstrcat也替换成安全的字符串操作函数,比如StringCchCopyW和StringCchCatW(需要包含Strsafe.h头文件),避免缓冲区溢出的风险:
// 替换lstrcpy(psz, wsz) StringCchCopyW(psz, /* psz的缓冲区大小,建议补充为函数参数 */, wsz); // 替换lstrcat(psz, ...) StringCchCatW(psz, /* psz的缓冲区大小 */, g_szDecimal);
如果psz的缓冲区大小是已知的,最好把它作为参数传入函数,这样安全函数能准确判断是否会溢出。
内容的提问来源于stack exchange,提问作者ncant
相关产品推荐
相关产品推荐

