原始的代码来自:【MoreWindows工做笔记5】StrFormatByteSize64 高端大气的显示文件大小windows
可是代码中有一个BUG,你看出什么问题来了吗?api
// 【MoreWindows工做笔记5】StrFormatByteSize64 高端大气的显示文件大小 #include <stdio.h> #include <math.h> #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") void NormFileSize(LONGLONG file_length, char* buffer, int buffer_size) { static double BASE_NUMBER = 1024.0; static char* SIZE_NAME[] = {"B","KB", "MB", "GB", "TB", "PB"}; double length = static_cast<double>(file_length); int i = 0; while (i < ARRAYSIZE(SIZE_NAME) && length > BASE_NUMBER) { length /= BASE_NUMBER; i++; } sprintf(buffer, "%lf %s", length, SIZE_NAME[i]); } int main() { printf(" 【MoreWindows工做笔记5】StrFormatByteSize64 高端大气的显示文件大小\n"); printf(" - http://blog.csdn.net/morewindows/article/details/16358955 -\n"); printf(" -- By MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); LONGLONG file_length = 34578; for (int i = 0; i < 10; i++) { printf("字节数 = %15I64d -- 文件大小:", file_length); char file_length_str1[100] = {0}; NormFileSize(file_length, file_length_str1, 100); printf("%15s ", file_length_str1); WCHAR file_length_str2[100] = {0}; StrFormatByteSizeW(file_length, file_length_str2, 100); // StrFormatByteSizeW会截断尾数 printf("%ls\n", file_length_str2); // 还能够试试StrFormatKBSize,这个只用KB来表示 file_length *= 11; } return 0; }
将9223372036854775807代入函数NormFileSize()
[文件为testprintf.cpp]
数组
#include <windows.h> #include <stdio.h> #include <tchar.h> #include <stdio.h> #include <math.h> #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") void NormFileSize(LONGLONG file_length, char* buffer, int buffer_size) { static double BASE_NUMBER = 1024.0; char* SIZE_NAME[] = {"B","KB", "MB", "GB", "TB", "PB"}; double length = static_cast<double>(file_length); int i = 0; while (i < ARRAYSIZE(SIZE_NAME) && length > BASE_NUMBER) { length /= BASE_NUMBER; i++; } sprintf(buffer, "%lf %s", length, SIZE_NAME[i]); } int main() { printf(" 【MoreWindows工做笔记5】StrFormatByteSize64 高端大气的显示文件大小\n"); printf(" - http://blog.csdn.net/morewindows/article/details/16358955 -\n"); printf(" -- By MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n"); LONGLONG file_length = 34578; char file_length_str1[100] = {0}; WCHAR file_length_str2[100] = {0}; //for (int i = 0; i < 10; i++) //{ // printf("字节数 = %15I64d -- 文件大小:", file_length); // NormFileSize(file_length, file_length_str1, 100); // printf("%15s ", file_length_str1); // StrFormatByteSizeW(file_length, file_length_str2, 100); // StrFormatByteSizeW会截断尾数 // printf("%ls\n", file_length_str2); // 还能够试试StrFormatKBSize,这个只用KB来表示 // file_length *= 11; //} file_length=9223372036854775807; NormFileSize(file_length, file_length_str1, 100); return 0; }
接着咱们要来抓鬼--为何会出现这个问题呢?
在下面所示的这个循环内,i值一直都是合法的,并且语义上彻底没有问题,函数
while (i < ARRAYSIZE(SIZE_NAME) && length > BASE_NUMBER)
{
length /= BASE_NUMBER;
i++;
}.net
可是循环下面的代码引用了这个变量,通常状况下,不会有问题,而后有人在问---咱们必定要把没问题的东西测出问题来吗?可是若是在极端状况下,好比代入很大的值,因而退出循环后i==ARRAYSIZE(SIZE_NAME),咱们知道,C++的数组const int MAX_INDEX=1000;int array[MAX_INDEX]下标范围是0~MAX_INDEX-1,元素为array[0],array[1],...array[MAX_INDEX-1],使用array[MAX_INDEX]就是越界!!!解决办法就是在越界前结束循环:code
while (i < ARRAYSIZE(SIZE_NAME)-1 && length > BASE_NUMBER)
{
length /= BASE_NUMBER;
i++;
}
orm
#include <windows.h> #include <stdio.h> #include <tchar.h> TCHAR* Bytes2StringEx(const ULARGE_INTEGER ullSizeInBytes,TCHAR *lpszSizeInfo)//StrFormatByteSize64在ANSI工做不正常 { //from:MoreWindows <<StrFormatByteSize64 高端大气的显示文件大小>> //bytes //bytes/1024 kB //bytes/1024/1024 MB //bytes/1024/1024/1024 GB //bytes/1024/1024/1024/1024 TB long double FileSize= static_cast<long double>(ullSizeInBytes.QuadPart); long double BASE_NUMBER = 1024.0; TCHAR *UnitName[] = {TEXT("B"),TEXT("kB"), TEXT("MB"),TEXT("GB"), TEXT("TB"),TEXT("PB")}; int i = 0; int max_index=sizeof(UnitName)/sizeof(UnitName[0]) ; //int max_index2=ARRAYSIZE(UnitName); while ( i<max_index-1 && FileSize>1024.0 ) { FileSize /= 1024.0; i++; } TCHAR *un=UnitName[i];//虽然上面的while中i不会超出max_index可是,当超出时,下面引用到的正是超出的这个下标 #pragma warning(disable:4996) _sntprintf(lpszSizeInfo,10230, TEXT("%lf %s"),FileSize, un); return lpszSizeInfo; } TCHAR* Bytes2StringEx2(const ULARGE_INTEGER ullSizeInBytes,TCHAR *lpszSizeInfo)//StrFormatByteSize64在ANSI工做不正常 { //from:MoreWindows <<StrFormatByteSize64 高端大气的显示文件大小>> // http://blog.csdn.net/morewindows/article/details/16358955#comments // ulx.QuadPart=14757395258967641292;//代入这个天文数字,而后已经不是什么PB //bytes //bytes/1024 kB //bytes/1024/1024 MB //bytes/1024/1024/1024 GB //bytes/1024/1024/1024/1024 TB long double FileSize= static_cast<long double>(ullSizeInBytes.QuadPart); TCHAR *StorageUnit[] = {TEXT("B"),TEXT("kB"), TEXT("MB"),TEXT("GB"),TEXT("TB"),TEXT("PB"),TEXT("EB"),TEXT("ZB"),TEXT("YB"),TEXT("BB"),TEXT("NB"),TEXT("DB")}; const int UNIT_MAX_INDEX=sizeof(StorageUnit)/sizeof(StorageUnit[0]); const long double BASE_NUMBER = 1024.0; int i = 0; while ( i<UNIT_MAX_INDEX-1 && FileSize>BASE_NUMBER )//bug fixed:虽然上面的while中i不会超出UNIT_MAX_INDEX可是,当超出时,下面引用到的正是超出的这个下标因此要减一:i<UNIT_MAX_INDEX-1 { FileSize /=BASE_NUMBER; i++; } #pragma warning(disable:4996) _stprintf(lpszSizeInfo,TEXT("%lf%s"),FileSize, StorageUnit[i]); return lpszSizeInfo; } int _tmain() { ULARGE_INTEGER ulx; ulx.QuadPart=-1;//(unsigned long long)-1==18446744073709551615,0xcccccccccccccccc=14757395258967641292;//代入这个天文数字,而后已经不是什么PB TCHAR lpszSizeInfo[20]; _tprintf(TEXT("%I64u bytes"),ulx.QuadPart ); Bytes2StringEx(ulx,lpszSizeInfo); _tprintf(TEXT("=%s "),lpszSizeInfo); Bytes2StringEx2(ulx,lpszSizeInfo); _tprintf(TEXT("=%s\n"),lpszSizeInfo); getchar();//pause return 0; }