2014-11-20 1 views
3

컨트롤이 '}'로 바뀌면 아래 코드가 충돌합니다. FieldByName() -> AsString을 변수로 대체하거나 실행되지 않으면 else를 제거하면 충돌이 발생하지 않습니다. AV가 발생할 때 '=='이 SameText로 대체되었습니다. '>'가 도시된다 분해 찾고충돌하는 디 어셈블 링 된 C++ 코드 분석

bool __fastcall TJwsSalesMethods::IsPORequiredForOrderAndCustomer(const String& OrderID, const String& CustomerID) 
{ 
    bool PORequired = false; 

    if (IsOrderCustomerPositioned(FqryWork01, CustomerID, OrderID)) // This function executes an SQL statement using FqryWork01->Open() 
    { 
    //String RequirePO = FqryWork01->FieldByName("RequirePO")->AsString; // Using variable instead will solve 
    if (SameText(FqryWork01->FieldByName("RequirePO")->AsString, "Y")) 
    { 
     PORequired = true; // This block is executed 
    } 
    else if (SameText(FqryWork01->FieldByName("RequirePO")->AsString, "N")) 
    { 
     PORequired = false; 
    } 
    else 
    { 
     PORequired = IsPORequiredForCustomer(CustomerID); 
    } 
    } //AV occurs here 

    return PORequired; 
} 

,

0053a40c  public JwsSalesUtil.cpp.TJwsSalesMethods.IsPORequiredForOrderAndCustomer: ; function entry point 
0053a40c 11784 push ebp 
0053a40d   mov  ebp, esp 
0053a40f   add  esp, -$54 
0053a412   mov  [ebp-$48], ecx 
0053a415   mov  [ebp-$44], edx 
0053a418   mov  [ebp-$40], eax 
0053a41b   mov  eax, $7cf0e0 
0053a420   call +$18c497 ($6c68bc)  ; __InitExceptBlockLDTC 
0053a425 11786 mov  byte ptr [ebp-$49], 0 
0053a429 11791 push dword ptr [ebp-$44] 
0053a42c   mov  ecx, [ebp-$48] 
0053a42f   xor  edx, edx 
0053a431   mov  eax, [ebp-$40] 
0053a434   call -$1ec9d ($51b79c)  ; JwsSalesUtil.cpp.TJwsSalesMethods.IsOrderCustomerPositioned 
0053a439   test al, al 
0053a43b   jz  loc_53a586 
0053a441 11794 mov  word ptr [ebp-$2c], $c 
0053a447   mov  edx, $7c1544   ; 'RequirePO' 
0053a44c   lea  eax, [ebp-4] 
0053a44f   call +$18ef14 ($6c9368)  ; System.UnicodeString.Create 
0053a454   inc  dword ptr [ebp-$20] 
0053a457   mov  edx, [eax] 
0053a459   mov  ecx, [ebp-$40] 
0053a45c   mov  eax, [ecx+$80] 
0053a462   call +$20285d ($73ccc4)  ; Data.Db.TDataSet.FieldByName (dbrtl180.bpl) 
0053a467   mov  [ebp-$50], eax 
0053a46a   lea  eax, [ebp-8] 
0053a46d   call -$135786 ($404cec)  ; ustring.h.System.UnicodeString.Create 
0053a472   mov  edx, eax 
0053a474   inc  dword ptr [ebp-$20] 
0053a477   mov  eax, [ebp-$50] 
0053a47a   mov  ecx, [eax] 
0053a47c   call dword ptr [ecx+$84] 
0053a482   lea  edx, [ebp-8] 
0053a485   push dword ptr [edx] 
0053a487   mov  edx, $7c154e 
0053a48c   lea  eax, [ebp-$c] 
0053a48f   call +$18eed4 ($6c9368)  ; System.UnicodeString.Create 
0053a494   inc  dword ptr [ebp-$20] 
0053a497   mov  edx, [eax] 
0053a499   pop  eax 
0053a49a   call +$20109d ($73b53c)  ; System.Sysutils.SameText (rtl180.bpl) 
0053a49f   push eax 
0053a4a0   dec  dword ptr [ebp-$20] 
0053a4a3   lea  eax, [ebp-$c] 
0053a4a6   mov  edx, 2 
0053a4ab   call +$18f120 ($6c95d0)  ; System.UnicodeString.Destroy 
0053a4b0   dec  dword ptr [ebp-$20] 
0053a4b3   lea  eax, [ebp-4] 
0053a4b6   mov  edx, 2 
0053a4bb   call +$18f110 ($6c95d0)  ; System.UnicodeString.Destroy 
0053a4c0   pop  ecx 
0053a4c1   test cl, cl 
0053a4c3   jz  loc_53a4ce 
0053a4c5 11796 mov  byte ptr [ebp-$49], 1 
0053a4c9 11797 jmp  loc_53a566 

경우 그 밖의 다른 잘리고

0053a566 11806 dec  dword ptr [ebp-$20] 
0053a569   lea  eax, [ebp-$14] 
0053a56c   mov  edx, 2 
0053a571  > call +$18f05a ($6c95d0)  ; System.UnicodeString.Destroy 
0053a576   dec  dword ptr [ebp-$20] 
0053a579   lea  eax, [ebp-8] 
0053a57c   mov  edx, 2 
0053a581   call +$18f04a ($6c95d0)  ; System.UnicodeString.Destroy 
0053a586 11812 mov  al, [ebp-$49] 
0053a589   mov  edx, [ebp-$3c] 
0053a58c   mov  fs:[0], edx 
0053a593 11813 mov  esp, ebp 
0053a595   pop  ebp 
0053a596   ret 

는 AV 53a566 위치에서 계속 발생한다. 제 질문은, 왜 3이 생성되고 첫 번째 블록에서 2 개만 파괴되고 나머지 2 개는 맨 아래에 있습니까? 그래서 실행 된 코드를 합하면 3이 생성되고 4가 파괴됩니다. 나는 또한 어떤 문자열이 Create와 Destroy에 해당하는지 알지 못한다. "RequirePO", AsString 및 "Y"는 세 개의 Create를 구성하고 다른 하나는 create point 중 하나를 가리킬 수 있습니다. 어쩌면 나는 그것을 올바르게 읽지 않을 것이다.

감사합니다.

감사합니다, 매튜 기쁨

+0

'String','AsString' 및'SameText'는 무엇입니까? – Barry

+1

이 디버깅에는 어셈블리 코드의 덤프가 필요합니다. 코드를 살펴보면 포인터를 사용하고 있으며 모두가 NULL이 아니라고 가정합니다. – PaulMcKenzie

+0

@PaulMcKenzie 어셈블리를 들여다 보는 것은 최후의 수단이었습니다. 새로운 것이나 자유로운 것이 없습니다. 모두 스택에 생성됩니다. 나의 의심은 옳지 않다는 것이다. 이 특정 코드는 수년간 테스트되었습니다. ==에서 SameText로 다시 고려하면 이제 AV가 발생합니다. 분해를 더 간단하게하기 위해 점검 중 하나를 제거했습니다. –

답변

2

나에게 컴파일러에서 CODEGEN 버그처럼 보인다. 0x0053a566에있는 코드 비트는 [ebp-$14]의 주소를 인자로 사용하여 System.UnicodeString.Destroy을 호출합니다. 그러나 [ebp-$14]은 초기화되지 않은 것 같습니다.

나는 [ebp-$14]이 주위에 점프하는 (즉, else ifelse 조항에 해당)이 생략 코드의 스트레칭에 System.UnicodeString.Create 호출에 의해 초기화됩니다 내기 것이다.

+0

asm을 들여다 보았을 때 합리적인 답/논평. 버그가 있으며 SameText와 FieldName-> AsString의 조합으로 asm 이상을 재현 할 수 있습니다. 대부분의 경우 충돌이 발생하지 않지만 버그 이상이 있습니다. 나는 더 볼 것이다. 감사. –

+0

Micheal, 그게 답입니다. ini는 내가 잘라낸 부분에 있으므로 생성되지 않은 것을 삭제합니다. 흥미롭게도 두 번째 init (else if)는 첫 번째 init 전에 파괴됩니다. 내가 '=='로 바꾸면 if asm에서 3 개의 Create를보고 3은 Destroys라고 생각합니다. asm을 도와 주셔서 감사합니다. 나는 단지 기본적인 것들을 알고 있습니다. Embarcadero를 통해 지원 사례를 기록 할 것입니다. –

+0

@MathewJoy'[ebp- $ 14]'문자열을 생성해야하는 코드를 찾을 수 있습니까? 그것은 왜 문제가 생겼는지에 대해 밝혀 줄 것입니다. (이것은 또한 나를 위해 몇 가지 벨소리를 울리며, AnsiStrings가 속성 사용법과 함께 적절하게 생성되거나 삭제되지 않은 과거에 제출 된 버그가 있습니다) –