[转]Protel 99 SE 'Format '%x' invalid or... 的分析
(该文为网上搜集)之前在笔记本上从来没出现过这个问题, 相同的安装文件. 已经打了protel99seservicepack6的补丁. 换了4核的台式机基本每天都有几次...这个问题在网上搜索, 回答多是不能用太好的机器否则Protel 99 SE 就会有很多问题, 经过分析实际还真是这样的.
Od载入 Client99SE.exe 断点到 Kernel32->RaiseException, 因为这是个delphi未处理异常. 运行进程等待 Client99SE.exe 抛出异常.当调用RaiseException 时查看调用栈定位到函数0DF61357 55 push ebp0DF61358 68 9414F60D push 0DF614940DF6135D 64:FF30 push dword ptr fs:0DF61360 64:8920 mov dword ptr fs:, esp0DF61363 C606 00 mov byte ptr , 00DF61366 E8 CD03E9FF call <jmp.&kernel32.GetTickCount>0DF6136B 8BD8 mov ebx, eax0DF6136D 8D85 FCFEFFFF lea eax, dword ptr 0DF61373 50 push eax0DF61374 A1 7CF1F70D mov eax, dword ptr 0DF61379 83C0 11 add eax, 110DF6137C 8985 E4FEFFFF mov dword ptr , eax0DF61382 C685 E8FEFFFF 04 mov byte ptr , 40DF61389 C685 ECFEFFFF 7E mov byte ptr , 7E0DF61390 C685 F0FEFFFF 02 mov byte ptr , 20DF61397 899D F4FEFFFF mov dword ptr , ebx0DF6139D C685 F8FEFFFF 00 mov byte ptr , 00DF613A4 8D95 E4FEFFFF lea edx, dword ptr 0DF613AA B9 02000000 mov ecx, 20DF613AF B8 AC14F60D mov eax, 0DF614AC ; ASCII "%s\%s%x.tmp"0DF613B4 E8 0703E9FF call <jmp.&Vcl50.Sysutils::Format>0DF613B9 8B95 FCFEFFFF mov edx, dword ptr 0DF613BF 8D85 00FFFFFF lea eax, dword ptr 0DF613C5 B9 FF000000 mov ecx, 0FF0DF613CA E8 71FEE8FF call <jmp.&Vcl50.System::LStrToString>0DF613CF EB 69 jmp short 0DF6143A0DF613D1 E8 6203E9FF call <jmp.&kernel32.GetTickCount>0DF613D6 8BD8 mov ebx, eax0DF613D8 8D85 E0FEFFFF lea eax, dword ptr 0DF613DE 50 push eax0DF613DF A1 7CF1F70D mov eax, dword ptr 0DF613E4 83C0 11 add eax, 110DF613E7 8985 E4FEFFFF mov dword ptr , eax0DF613ED C685 E8FEFFFF 04 mov byte ptr , 40DF613F4 C685 ECFEFFFF 7E mov byte ptr , 7E0DF613FB C685 F0FEFFFF 02 mov byte ptr , 20DF61402 899D F4FEFFFF mov dword ptr , ebx0DF61408 C685 F8FEFFFF 00 mov byte ptr , 00DF6140F 8D95 E4FEFFFF lea edx, dword ptr 0DF61415 B9 02000000 mov ecx, 20DF6141A B8 C014F60D mov eax, 0DF614C0 ; ASCII "%s\s%x%.tmp"0DF6141F E8 9C02E9FF call <jmp.&Vcl50.Sysutils::Format>0DF61424 8B95 E0FEFFFF mov edx, dword ptr 0DF6142A 8D85 00FFFFFF lea eax, dword ptr 0DF61430 B9 FF000000 mov ecx, 0FF0DF61435 E8 06FEE8FF call <jmp.&Vcl50.System::LStrToString>0DF6143A 8D85 DCFEFFFF lea eax, dword ptr 0DF61440 8D95 00FFFFFF lea edx, dword ptr 0DF61446 E8 EDFDE8FF call <jmp.&Vcl50.System::LStrFromString>0DF6144B 8B85 DCFEFFFF mov eax, dword ptr 0DF61451 E8 B201E9FF call <jmp.&Vcl50.Sysutils::FileExists>0DF61456 84C0 test al, al0DF61458 ^ 0F85 73FFFFFF jnz 0DF613D10DF6145E 8BC6 mov eax, esi0DF61460 8D95 00FFFFFF lea edx, dword ptr 0DF61466 E8 2DFCE8FF call <jmp.&Vcl50.System::PStrCpy>0DF6146B 33C0 xor eax, eax0DF6146D 5A pop edx0DF6146E 59 pop ecx0DF6146F 59 pop ecx0DF61470 64:8910 mov dword ptr fs:, edx0DF61473 68 9B14F60D push 0DF6149B0DF61478 8D85 DCFEFFFF lea eax, dword ptr 0DF6147E BA 02000000 mov edx, 20DF61483 E8 90FDE8FF call <jmp.&Vcl50.System::LStrArrayClr>0DF61488 8D85 FCFEFFFF lea eax, dword ptr 0DF6148E E8 7DFDE8FF call <jmp.&Vcl50.System::LStrClr>0DF61493 C3 retn0DF61494 ^ E9 3FFDE8FF jmp <jmp.&Vcl50.System::HandleFinally>0DF61499 ^ EB DD jmp short 0DF614780DF6149B 5E pop esi0DF6149C 5B pop ebx0DF6149D 8BE5 mov esp, ebp0DF6149F 5D pop ebp0DF614A0 C3 retn堆栈上有一块字符串0013DD1C 0F817B8C ASCII "C:\PROGRA~1\DESIGN~1\\System\Temp\~35C52FB.tmp"问题出在第二个调用format函数时给予的第一个参数 "%s\s%x%.tmp" 上.用ida插件转换到c代码int __fastcall sub_571334(int a1){ int v1; // esi@1 int v2; // ST04_4@1 DWORD v4; // eax@1 DWORD v5; // eax@2 int v6; // @1 int v7; // @1 int v8; // @1 int v9; // @1 int v10; // @1 char v11; // @1 char v12; // @1 char v13; // @1 DWORD v14; // @1 char v15; // @1 char v16; // @1 v6 = 0; v7 = 0; v8 = 0; v1 = a1; v2 = *MK_FP(__FS__, 0); *MK_FP(__FS__, 0) = &v9; *(_BYTE *)a1 = 0; v4 = GetTickCount(); v10 = dword_58F17C + 17; v11 = 4; v12 = 126; v13 = 2; v14 = v4; v15 = 0; Sysutils__Format(&str__s__s_x_tmp, &v10, &v8); System____linkproc___LStrToString(&v16, v8); while ( 1 ) { System____linkproc___LStrFromString(&v6, &v16); if ( !(unsigned __int8)Sysutils__FileExists(v6) ) break; v5 = GetTickCount(); v10 = dword_58F17C + 17; v11 = 4; v12 = 126; v13 = 2; v14 = v5; v15 = 0;
Sysutils__Format(&str__s_s_x__tmp, &v10, &v7); System____linkproc___LStrToString(&v16, v7); } System____linkproc___PStrCpy(v1, &v16); *MK_FP(__FS__, 0) = v2; System____linkproc___LStrArrayClr(&v6, 2); return System____linkproc___LStrClr(&v8);}可以看到这个函数用来完成生成不重复的随机文件名, 当机器太快硬盘太快时GetTickCount返回的值可能在两次调用中相同, 就会调用第二个format发生这个异常 因为Sysutils__Format(&str__s_s_x__tmp, &v10, &v7);处参数是错误的.Ps:我这c盘就一垃圾ssd...只要补丁字符串 "%s\s%x%.tmp" 为 "%s\%s%x.tmp" 就可以了.25735C732578252E746D70 -> 25735C257325782E746D70原来是写 Protel 99 SE 的大神当年没测试到...
我的机器貌似一直没有问题,我也是4核心的哇。 用AD的没这问题
页:
[1]