2009-05-16 5 views
2

저는 버그를 재현하고 원인을 찾는 데 큰 어려움을 겪었습니다. 발생은 완전히 무작위로 보입니다. 그래서 나는 초기화되지 않은 변수를 어딘가에서 의심했습니다.()입니다 즉, 내가 DoStuff - DoOtherStuff은() 중 하나를 "B"에서 수행되는 것처럼이로 인해 정의되지 않은 동작이 발생할 수 있습니까?

CMyClass obj; // A 
obj.DoStuff(); 

if (somebool) 
{ 
    CMyClass obj; // B 
    obj.DoStuff(); 
} 

obj.DoOtherStuff(); 

것 같다, 또는 B.DoStuff()는 종종 실제로 작동 :하지만 나는이 코드 조각을 발견 첫 번째 obj에서 실제로 호출되었습니다.

이 문제가 발생할 수 있습니까? 나는 컴파일러 경고가 있다고 생각하지 않는다. (필자는 도움이 될 수 있기를 희망하면서 코드를 수정했다.) 매우 인 것 같습니다. 실제 코드의이 부분은 내가 찾으려는 버그가있는 곳이지만, 아직 발견하지 못한 다른 이유가있을 수 있습니다.

답변

5

코드는 작성한대로 작동해야합니다. DoStuff()의 첫 번째 통화와 DoOtherStuff()의 마지막 통화는 A으로 만 전송할 수 있습니다.

if(somebool) { } 블록 내의 DoStuff()에 대한 호출은 B으로 만 전송할 수 있습니다. standard 가입일

:

3.3.2 로컬 범위

  1. 블록 (6.3)에서 선언 된 이름이 그 블록에 대해 로컬이다. 그것의 잠재적 범위는 선언 지점 (3.3.1)에서 시작하고 은 선언 영역의 끝에서 끝납니다.

그리고 :

3.3.7 이름

  1. 이름이 중첩 된 선언적 지역이나 파생 클래스에서 같은 이름의 명시 적 선언으로 숨길 수 있습니다 숨기기 (10.2). 말했다되고 그건

는, 아마도이 있었다 그 코드의 저자에 의해을 의도하지 않습니다. 변수의 이름이 같은 경우 해당 변수의 인스턴스가 하나 뿐이므로 루프 내에 만들어진 B 인스턴스는 실수입니다. 두 번째 인스턴스가 의미가 있는지 확인하기 위해 논리를 살펴 보았습니까?발렌틴은 전역 변수를 숨기이 모든 일 자체가 글로벌 변수와 동일한 이름을 가진 if 문

+0

네 가지 경우가있었습니다. – Srekel

+0

흥미 롭습니다. 그 (것)들에게 동일한 이름을주는 결정은 용의주하다. 물론 논리를 보지 않고서도 저자가 왜 그런 식으로 선택했는지 나는 알지 못합니다. 문제를 해결 한 이름을 바꿨습니까? –

+0

나는 그 (것)들을 똑같이 지명하는 것이 복사 - 붙여 넣기 "실수"이상이 아닌 것을 의심한다. 아직 코드를 테스트하지 않았으므로 아직 작동하는지 확실하지 않습니다. – Srekel

1

아니요. 일어날 수 없습니다.

컴파일러는 if 범위를 종료 할 때 B 객체가 제대로 파괴되고 살아있는 동안 자체 주소 공간에서 작동한다는 것을 보장합니다.

오류는 다른 곳에서 발생합니다.

3

은 다음 몇 가지 전역 객체에 대한 변경하는 그 블록 안에. 그러나 전역 범위 연산자 (: :) 당신이 글로벌 버전은 범위를 벗어난 경우에 따라서 지역 변수 B가 파괴

CMyClass obj; // A 
obj.DoStuff(); 
if (somebool) 
{ 
CMyClass obj; // B 
obj.DoStuff(); //does on B 
::obj.DoStuff(); //does on A 
} 
obj.DoOtherStuff(); //this will call A because B is destroyed 

에게 의미 컴파일러에게 할 수 있습니다. 전역 변수와 같은 이름을 가진 지역 변수를 갖는 것은 일반적으로 문제를 요구하기 때문에 가능하면 피하는 것이 좋습니다.

+2

또는 일부 클래스 정적 변수가 영향을받습니다. 또는 그들은 어떤 공장에서 얻은 공통된 물건을 공유합니다. –

+1

@Mykola - 좋은 점! – ChrisF

2

지역 변수의 범위에 포함해야 지적으로 obj.DoStuff() 않는 한

2

GCC를 사용하는 경우 - 예를 들어, 매우 미세한 버그 인 경우와 같은 경우에 경고를 내 보냅니다 -Wshadow를 사용할 수 있습니다.

그러나 이미 많은 사람들이 말했듯이 붙여 넣은 코드는 정확하고 예상 한대로 작동하며 정의되지 않은 동작이 아닙니다.

0

코드가 구문 상 올바르지 만 방법은 무엇을합니까? 스택 오버플로는 예를 들어 관찰하고있는 것처럼 유령 같은 행동을 유발할 수 있습니다.