2010-02-24 3 views
3

우리는 며칠 동안 이상한 사례를 디버깅 해왔고 버그를 다소 고립 시켰지만 여전히 의미가 없습니다. 어쩌면 여기에있는 누구라도 나에게 무슨 일이 일어나고 있는지에 대한 단서를 줄 수 있습니다.개체를 스택에서 생성하기 전에 unwind 될 수 있습니까?

문제는 코드 일부에서 발생하는 액세스 위반입니다.

는 기본적으로 우리는 다음과 같이 있습니다

void aclass::somefunc() { 
    try { 
    erroneous_member_function(*someptr); 
    } 
    catch (AnException) { 
    } 
} 

void aclass::erroneous_member_function(const SomeObject& ref) { 
    // { //<--scope here error goes away 
    LargeObject obj = Singleton()->Object.someLargeObj; //<-remove this error goes away 

    //DummyDestruct dummy1//<-- this is not destroyed before the unreachable 

    throw AnException(); 

    // } //<--end scope here error goes away 

    UnreachableClass unreachable; //<- remove this, and the error goes away 

    DummyDestruct dummy2; //<- destructor of this object is called! 
} 

이상한 소멸자가 호출되기 전에이 UnreachableClass을 파괴한다, 그리고 나는 DummyDestruct 개체를 삽입 할 때이 파괴되지 않습니다 같은 디버거에서 실제로 보이는 동안 . 그래서 LargeObject의 파괴가 잘못 될 것 같지 않습니다.

이 모든 것은 프로덕션 코드 중간에 있으며, 작은 예제로 격리하는 것은 매우 어렵습니다.

내 질문은 무엇이 문제의 원인인지에 대한 단서가 있습니까? 꽤 완벽한 기능의 디버거를 사용할 수 있지만 (Embarcadero RAD 스튜디오), 이제는 어떻게해야 할 지 잘 모르겠습니다.

아무에게 나 진행 방법에 대한 조언을 줄 수 있습니까?

는 업데이트 :

은 내가 던져 절 아래에 DummyDestruct 오브젝트를 배치하고, 소멸자에서 중단 점을 배치. 이 객체의 소멸자가 입력됩니다 (이 코드에만 해당).

+0

무엇을 연결할 수없는 상태에서 명시 적으로 생성자를 호출하면 어떻게됩니까? 일부 생성자가 사용되지 않는 한 로컬 변수는 선언 된 범위의 시작 부분에서 '초기화'된 것으로 생각합니다. – nothrow

+0

오류는 무엇입니까? 어느 선이 그것을 일으키는가? – phtrivier

+0

컴파일 할 때 어떤 최적화가 필요합니까? – Bill

답변

1

제공하신 정보로 모든 것이 진술 된 경우 가능한 유일한 대답은 컴파일러/최적화 프로그램의 버그입니다. 그냥 코멘트와 함께 여분의 범위를 추가하십시오 (이것은, 다시, 당신이 진술 한대로 모든 것이 정확하다면).

+1

나는 똑같은 생각을 가지고 있지만, 나는 이것을 받아 들일 수 없다. 그러한 중대한 오류가 컴파일러에 있다면 그것은 주목되었을 것입니다. (우리는 BCC 권을 사용하는 세계 유일의 회사가 아닙니까?). 상황은 제공되는 것과 같지만, 내가 말했듯이 이것은 대규모 프로젝트에 속하며, 많은 것들이 이전에 잘못 될 수 있습니다. 모든 종류의 메모리를 덮어 쓰면 복사 된 largeObject가 완전하게 무효/덮어 쓰기 될 수 있습니다. – daramarak

+0

Singleton() 메모리를 덮어 쓰거나 엉망이 될 가능성이 있습니까? 누군가가 싱글 톤 (Singleton)이나 다른 것을 확장하고 있습니까? – phtrivier

+0

@daramarak : * 우리는 숨은 참조를 사용하는 세계에서 유일하게 회사가 아닙니까? * 사용 된 숨은 참조 (BCC)를 본 적이 없거나 들어 본 적이 없습니다. 그것은 MSVS 또는 GCC 중 하나입니다. –

1

초기화되지 않은 포인터, 범위를 벗어난 어레이 액세스 등으로 인해 작성되는 경우가 종종 있습니다. 오류가 발생한 지점은 명시된 위치에서 완전히 제거 될 수 있습니다. 그러나 설명하는 증상에 따라이 기능에서 현지화 된 것으로 보입니다. LargeObject의 복사 생성자가 잘못 작동 할 수 있습니까? ref가 사용됩니까? 아마도 somePtr은 유효한 SomeObject을 가리키고 있지 않습니다. Singleton()이 유효한 개체에 대한 포인터를 반환하고 있습니까? 컴파일러 오류가 발생할 수 있습니다. 특히 적극적인 최적화가 설정된 경우에 특히 그렇습니다. 최적화가없는 버그를 다시 만들려고합니다.

+0

LargeObject에는 컴파일러에서 제공 한 것 이외의 생성자 또는 소멸자가 없습니다. 싱글 톤은 유효한 객체의 복사본을 반환하지만 손상되었을 수 있습니다. 그러나 손상된 코드가이 코드 부분에서 어떻게 잘못 될지를 볼 수는 없습니다. 특히 코드가 생성되지 않는 것처럼 보이면 스택에만 배치됩니다. – daramarak

+0

'Singleton()'에 의해 반환 된 타입에 대해'->'이 오버로드 되었습니까? 그렇다면 문제를 일으킬 수 있습니다. – Ari

+0

'AnException'의 생성자는 어떻습니까? BTW,이 법적 규정은 무엇입니까? 대문자를 기반으로'AnException'은 객체가 아닌 클래스 이름이라고 추측합니다. – Ari

1

시간 내 텔레파시 디버깅 기술을 연습합니다 :

내 추측은 응용 프로그램 스택 손상 버그가 있습니다. 이것은 호출 스택을 통해 쓰레기를 작성할 수 있습니다. 즉, 디버거가 중단 될 때 디버거가 함수를 잘못보고하고 있음을 의미합니다. 실제로는 소멸자가 아닙니다. 그 또는 당신이 잘못 디버거 정보를 해석하고 개체가 실제로 제대로 파괴되고있다,하지만 당신은 왜 몰라!

스택 손상이 발생한 경우 근본 원인을 파악하는 데 많은 시간을 할애해야합니다. 이것이 프로그램 전반에 걸친 진단 (예 : 어설트) 톤을 구현하는 것이 중요한 이유입니다. 그래서 이상한 부작용에 얽매이지 않고 스택 손상을 발견 할 수 있습니다.

+0

스택 손상은 제가 따라 온 가설입니다. 예외 전후에 스택을 검사하여 생성 된 객체에서 소멸자를 던지거나 CPU보기를 통해 코드를 추적하여 무언가 잘못 되었으면 찾습니다. 하지만 코드를 단계별로 살펴보면 전체 디버거가 나를 속이고, 실제로 호출되는 함수는 전혀 호출되지 않는다고 제안 하시겠습니까? – daramarak

+0

아니, 그다지 멀리 가지 않을거야 ... 내가 말한 건 스택 손상이 이미 발생했다면 디버거가 호출 스택에 잘못된 정보를 보여줄 수 있다는 것입니다. – AshleysBrain

+0

호출 스택에만 의존하지 않고 코드를 단계별로 실행하고 있으므로 적어도 실행되는 위치와 실행되지 않는 위치를 신뢰할 수 있다고 생각합니다. – daramarak

0

이것은 아주 긴 장면 일지 모르지만 어쨌든 거기에 넣을 것입니다 ...

당신은 볼랜드를 사용한다고 말합니다 - 어떤 버전입니까? 그리고 당신은 문자열에서 에러를 본다고합니다 - STL? 프로젝트에 winsock2가 포함되어 있습니까?

내가 물어 본 이유는 borland 6 (2002)와 winsock을 사용할 때 헤더가 구조 패킹을 엉망으로 만든 것처럼 보였고 다른 번역 단위가 std의 메모리 레이아웃에 대해 다른 생각을 가졌음을 의미합니다. 문자열은 번역 단위에 포함 된 헤더에 따라 예상치 못한 결과를 초래할 수 있습니다.

+0

이런 일이 문제라면 놀랄 일이 아닙니다. 그러나 winsock2가 우리 코드에서 사용되지 않는다고 말하는 것은 유감입니다. – daramarak

0

문자열을 언급 한 이후로 또 다른 야생의 추측이 있습니다. 나는 (STL) 문자열 복사가 게으른 방식으로 이루어진 적어도 하나의 구현을 안다. (즉, 변경 될 때까지 문자열 내용의 실제 복사가 일어나지 않으며 "복사"는 단순히 대상 문자열 객체 소스와 같은 버퍼를 가리킨다). 이 특정 구현 (GNU)에는 과도한 복사로 인해 참조 카운터 (실제로 복사 한 후 동일한 실제 문자열 메모리를 사용하는 객체 수)가 0으로 롤오버하여 모든 종류의 장난이 발생하는 버그가 있습니다. 나는이 버그를 나 자신과 마주 치지 못했다. (ref 카운터는 32 비트 숫자가 될 것이라고 생각할 것이기 때문에 이것을 말합니다. 그리고 그 이상으로 굴러가는 가능성은 아주 적기 때문에 문제를 적절하게 설명하지는 못합니다.)

+0

우리 문제는 그런 것 같지 않습니다. 특히 할당 해제 된 문자열은 범위에서 할당 된 모든 스택 객체 위에 스택의 사용되지 않는 부분에있는 것처럼 보입니다. – daramarak

관련 문제