2007年12月1日 星期六

goto CLEANUP or TRAP

這幾天犯了一個嚴重的錯誤, 害 XXXNT 在 64-bit Vista 上一執行就會 GPF

void foo()
{
 if (something is wrong)
 goto CLEANUP;
 char *ptr = NULL;
 ptr = new char [100];
CLEANUP:
 if (ptr) delete [] ptr;
}

這段 code 會被編譯成:

 cmp something_is_wrong
 je CLEANUP1
 push 64h
 call operator new
 add esp,4
 jmp CLEANUP2
CLEANUP1:
 mov eax, dword ptr [esp+4]
CLEANUP2:
 test eax,eax
 je END
 push eax
 call operator delete
 add esp,4
END:
 xor eax,eax
 ret

也就是說, 假如真的執行到了 goto 指令, 則將存取到 esp+4 這塊記憶體, 而其內容並非我們所想像的 NULL, 因此將會引發不可預期的後果.

幸好, 當 VC8 的 compile warning level 開到 /W4 的時候, 這種 code 將會引發一個 C4701 warning

1 則留言:

Mesh Wu 提到...

怎麼很像是某 architect 試出來的 XD