2009-03-19 4 views
10

나는이 코드 조각이 내게 부러 졌다고 생각했지만, thisnull입니다. 난 그냥이있을 수있는 방법이 이것이 우리가if (! this) {false false; }

if (!this) { return false; } 

null

MyObject::func() 내부에 일반 메소드 호출과 같은

myObject->func(); 

안에 할 수있는 방법을 얻을하지 않습니다 첫 번째 라인은 null (?) 메소드 대신에 NullPointerException을 던지겠습니까?

+0

.net 특정 제품입니까? - 당신은 태그를 변경하고 싶을 수도 있습니다, 많은 C++ 사용자가 걸러 낼 것입니다 .net –

+1

NullPointerException은 이것이 C++ 질문이 아니라고 믿게합니다. 기음#? – Tom

답변

22

이있는 경우 : 다음에 무슨 일이 것은 func가 가상인지에 따라 달라집니다

MyObject *o = NULL; 

o->func(); 

. 그렇다면 vtable을 가져올 객체가 필요하기 때문에 충돌이 발생합니다. 그러나 가상이 아닌 경우이 포인터를 NULL로 설정하여 호출이 진행됩니다.

표준은 이것이 "정의되지 않은 동작"이라고 말합니다. 그래서 아무 일도 일어나지 않을 것이지만 일반적인 컴파일러는 포인터가 NULL인지 여부를 확인하지 않는 코드를 생성합니다. 잘 알려진 라이브러리 중 일부는 내가 설명한 동작에 의존합니다. MFC는 null 포인터에서 호출 할 수있는 SafeGetHandle과 같은 함수를 가지고 있으며이 경우 NULL을 반환합니다.

당신은 재사용 가능한 도우미 함수 작성 할 수 있습니다 :

void CheckNotNull(void *p) 
{ 
    if (p == NULL) 
     throw NullPointerException(); 
} 

당신은 다음 this를 포함한 모든 인수를 확인하는 함수의 시작 부분에서 그것을 사용할 수 있습니다 :

CheckNotNull(this); 
+0

그냥 명확히하기 위해 ... dereferencing NULL은 표준에 의해 정의되지 않은 동작입니다. MFC 정말 이것에 의존해서는 안됩니다. 그것이 구현 정의 된 것이라면, 상황은 달라질 것입니다. 경쟁 조건을 "수정"하려는 시도가 잘못되었을 가능성이 있습니다. –

+0

나는이 이야기가 적절하다고 생각한다. http://www.gotw.ca/conv/002.htm –

+0

이야기에 대한 도덕적 대안 : CheckNotNull을 구현하고 "Do not an asshole, Bob ! " –

1
if(this == null) 
    throw new NullPointerException; 
if(!this) 
    return false; 
+0

왜 예외에 대한 포인터를 던집니까? –

+0

왜 NULL을 두 번 테스트 했습니까? – Eclipse

+0

코드가 C#처럼 보입니다. 그렇지 않습니까? – mmmmmmmm

-1

이 = = null은 삭제 된 객체에 대해 메소드를 호출하거나 객체가이 포인터를 덮어 쓰지 않아야하는 메모리에 기록하는 경우에만 발생해야합니다.

코드와 관련하여이 문제를 해결하기보다는 실제로 무엇이 잘못된 것인지 조사해야합니다.

+0

개체를 삭제해도 포인터가 null로 설정되지 않습니다. –

+0

+1 Mark Ransom의 의견입니다. – Tom

0

이 포인터는 다음과 같은 경우에 널 (null)이 될 수 있습니다

class Test 
{ 

public: 
    bool f(); 

private: 
    int m_i; 
}; 


bool Test::f() 
{ 
    if(!this) 
    { 
     return false; 
    } 

    m_i = 0; 
    return true; 

} 


int main(int argc, char **argv) 
{ 
    Test* p = new Test; 
    delete p; 
    p = NULL; 

    p->f(); 
} 

나는 누군가가 액세스 위반 예외를 방지하기 위해 빠른 해킹을했던 것 같아요.

+0

나는 f를 호출하려고하면 곧바로 충돌하지 않는다는 것에 놀랄뿐입니다 ... p가 NULL이면 p-> 아무것도 seg-fault 여야합니다 ... –

1

this이 null 일 수 있습니다. 나는이 코드가 객체가 아직 초기화가 완료되지 않았거나 삭제 된 경쟁 조건을 (심하게) 감지하려한다고 의심한다.

+0

"this"를 변경할 수 없습니다. . 그것은 가치입니다. (= "this"는 객체가 아닙니다.) 당신은 이것을 "자기"가이 포인터라고 상상해보십시오. T * self_ = this; #define self (self_ + 0) // 당신이 할 수 없었던 (self + 0) = ... –

+0

어, 네가 맞아.나는 "그러나 쓰여질 수는 없다"고 말하려고했다. –

1

(this == NULL)은 표준에 따라 정의되지 않은 동작입니다. 난 당신이 체크 :

우리가 다음 전화를 걸 가정을 제거해야한다고 생각 :

((CSomeClass*) 0)->method(); 

동작이 이미 정의되어 있지, 왜 CSomeClass :: 방법이 ==의 NULL에 대한 검사를하고 귀찮게?

편집 됨 : 나는 당신의 컴파일러가 처리 할 수 ​​있다고 가정 (0 ==이) 당신이 멤버 변수를 사용하지 않는 경우,하지만 어디에 가상 테이블 포인터를 찾을까요? 이 경우 귀하의 수업은 다형성을 사용할 수 없습니다.

+0

체크인을하는 이유 중 하나는 컴파일러가 자동으로 표준을 적용하지 않는다는 것입니다. –

+0

처음에는 NULL로 부르지 않을 것이고, 그 검사는 전혀 필요하지 않을 것입니다. 또는 - 내가 확인하면 통화 시간에. 피 호출자가 그렇게 불가능한 일을 할 때 왜 피 호출자가 걱정해야합니까? 그 상황에 대한 어설트를 포함하는 좋은 스마트 포인터는 내가 괜찮다고 생각한다. –

+0

네, assert (obj) 코드 (메소드가 아님) 또는 스마트 포인터가 문제를 탐지하는 데 도움이된다. 일반적으로 나는 어떤 일이 일어나서는 안되며 주장되어야하고 어떤 것이 검사되어야하는지 많은 개발자를 보았다. – bayda

2

이러한 종류의 오류를 의도적으로 트랩하는 방법은 null 포인터 인수로 생성시 throw하는 포인터 래퍼 클래스 (shared_ptr과 유사)를 사용하고 있습니다. 참조 해제 될 때도 throw 될 수 있지만 조금 늦은 것입니다. 아무 것도없는 것보다 나은 것 같습니다.

+0

나는 첫번째 boost :: shared_ptr이 던질 것이라고 생각했다. 하지만 그것을 찾은 후, 그것은 내 대답을 삭제해야만했다 : (분명히 그것은 구현 여부에 상관없이 무언가가 던져 지거나 그렇지 않다.) 그럼에도 불구하고, GCC에서는 어설 션 오류가 발생한다. –