(该文为网上搜集)
之前在笔记本上从来没出现过这个问题, 相同的安装文件. 已经打了protel99seservicepack6的补丁. 换了4核的台式机基本每天都有几次... 这个问题在网上搜索, 回答多是不能用太好的机器否则Protel 99 SE 就会有很多问题, 经过分析实际还真是这样的.
Od载入 Client99SE.exe 断点到 Kernel32->RaiseException, 因为这是个delphi未处理异常. 运行进程等待 Client99SE.exe 抛出异常. 当调用RaiseException 时查看调用栈定位到函数 0DF61357 55 push ebp 0DF61358 68 9414F60D push 0DF61494 0DF6135D 64:FF30 push dword ptr fs:[eax] 0DF61360 64:8920 mov dword ptr fs:[eax], esp 0DF61363 C606 00 mov byte ptr [esi], 0 0DF61366 E8 CD03E9FF call <jmp.&kernel32.GetTickCount> 0DF6136B 8BD8 mov ebx, eax 0DF6136D 8D85 FCFEFFFF lea eax, dword ptr [ebp-104] 0DF61373 50 push eax 0DF61374 A1 7CF1F70D mov eax, dword ptr [DF7F17C] 0DF61379 83C0 11 add eax, 11 0DF6137C 8985 E4FEFFFF mov dword ptr [ebp-11C], eax 0DF61382 C685 E8FEFFFF 04 mov byte ptr [ebp-118], 4 0DF61389 C685 ECFEFFFF 7E mov byte ptr [ebp-114], 7E 0DF61390 C685 F0FEFFFF 02 mov byte ptr [ebp-110], 2 0DF61397 899D F4FEFFFF mov dword ptr [ebp-10C], ebx 0DF6139D C685 F8FEFFFF 00 mov byte ptr [ebp-108], 0 0DF613A4 8D95 E4FEFFFF lea edx, dword ptr [ebp-11C] 0DF613AA B9 02000000 mov ecx, 2 0DF613AF 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 [ebp-104] 0DF613BF 8D85 00FFFFFF lea eax, dword ptr [ebp-100] 0DF613C5 B9 FF000000 mov ecx, 0FF 0DF613CA E8 71FEE8FF call <jmp.&Vcl50.System:StrToString> 0DF613CF EB 69 jmp short 0DF6143A 0DF613D1 E8 6203E9FF call <jmp.&kernel32.GetTickCount> 0DF613D6 8BD8 mov ebx, eax 0DF613D8 8D85 E0FEFFFF lea eax, dword ptr [ebp-120] 0DF613DE 50 push eax 0DF613DF A1 7CF1F70D mov eax, dword ptr [DF7F17C] 0DF613E4 83C0 11 add eax, 11 0DF613E7 8985 E4FEFFFF mov dword ptr [ebp-11C], eax 0DF613ED C685 E8FEFFFF 04 mov byte ptr [ebp-118], 4 0DF613F4 C685 ECFEFFFF 7E mov byte ptr [ebp-114], 7E 0DF613FB C685 F0FEFFFF 02 mov byte ptr [ebp-110], 2 0DF61402 899D F4FEFFFF mov dword ptr [ebp-10C], ebx 0DF61408 C685 F8FEFFFF 00 mov byte ptr [ebp-108], 0 0DF6140F 8D95 E4FEFFFF lea edx, dword ptr [ebp-11C] 0DF61415 B9 02000000 mov ecx, 2 0DF6141A 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 [ebp-120] 0DF6142A 8D85 00FFFFFF lea eax, dword ptr [ebp-100] 0DF61430 B9 FF000000 mov ecx, 0FF 0DF61435 E8 06FEE8FF call <jmp.&Vcl50.System:StrToString> 0DF6143A 8D85 DCFEFFFF lea eax, dword ptr [ebp-124] 0DF61440 8D95 00FFFFFF lea edx, dword ptr [ebp-100] 0DF61446 E8 EDFDE8FF call <jmp.&Vcl50.System:StrFromString> 0DF6144B 8B85 DCFEFFFF mov eax, dword ptr [ebp-124] 0DF61451 E8 B201E9FF call <jmp.&Vcl50.Sysutils::FileExists> 0DF61456 84C0 test al, al 0DF61458 ^ 0F85 73FFFFFF jnz 0DF613D1 0DF6145E 8BC6 mov eax, esi 0DF61460 8D95 00FFFFFF lea edx, dword ptr [ebp-100] 0DF61466 E8 2DFCE8FF call <jmp.&Vcl50.System:StrCpy> 0DF6146B 33C0 xor eax, eax 0DF6146D 5A pop edx 0DF6146E 59 pop ecx 0DF6146F 59 pop ecx 0DF61470 64:8910 mov dword ptr fs:[eax], edx 0DF61473 68 9B14F60D push 0DF6149B 0DF61478 8D85 DCFEFFFF lea eax, dword ptr [ebp-124] 0DF6147E BA 02000000 mov edx, 2 0DF61483 E8 90FDE8FF call <jmp.&Vcl50.System:StrArrayClr> 0DF61488 8D85 FCFEFFFF lea eax, dword ptr [ebp-104] 0DF6148E E8 7DFDE8FF call <jmp.&Vcl50.System:StrClr> 0DF61493 C3 retn 0DF61494 ^ E9 3FFDE8FF jmp <jmp.&Vcl50.System::HandleFinally> 0DF61499 ^ EB DD jmp short 0DF61478 0DF6149B 5E pop esi 0DF6149C 5B pop ebx 0DF6149D 8BE5 mov esp, ebp 0DF6149F 5D pop ebp 0DF614A0 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; // [sp+8h] [bp-124h]@1 int v7; // [sp+Ch] [bp-120h]@1 int v8; // [sp+28h] [bp-104h]@1 int v9; // [sp-Ch] [bp-138h]@1 int v10; // [sp+10h] [bp-11Ch]@1 char v11; // [sp+14h] [bp-118h]@1 char v12; // [sp+18h] [bp-114h]@1 char v13; // [sp+1Ch] [bp-110h]@1 DWORD v14; // [sp+20h] [bp-10Ch]@1 char v15; // [sp+24h] [bp-108h]@1 char v16; // [sp+2Ch] [bp-100h]@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[1], &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[1], &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[1], &v10, &v7);处参数是错误的. Ps:我这c盘就一垃圾ssd... 只要补丁字符串 "%s\s%x%.tmp" 为 "%s\%s%x.tmp" 就可以了. 25735C732578252E746D70 -> 25735C257325782E746D70 原来是写 Protel 99 SE 的大神当年没测试到...
|