>백엔드 개발 >C++ >C의 널 포인터에서 비가상 멤버 함수를 호출하는 것이 때때로 작동하는 이유는 무엇입니까?

C의 널 포인터에서 비가상 멤버 함수를 호출하는 것이 때때로 작동하는 이유는 무엇입니까?

DDD
DDD원래의
2024-12-13 16:58:10660검색

Why Does Calling a Non-Virtual Member Function on a Null Pointer in C   Sometimes Work?

C의 문제: Null 포인터에서 비가상 클래스 멤버 액세스

C에서 null에서 비가상 멤버 함수 호출 포인터가 예기치 않게 작동하여 이상한 퍼즐이 생길 수 있습니다. 흥미로운 코드 조각을 통해 이 동작을 자세히 살펴보겠습니다.

class Foo {
public:
    virtual void say_virtual_hi() {
        std::cout << "Virtual Hi";
    }

    void say_hi() {
        std::cout << "Hi";
    }
};

int main() {
    Foo* foo = 0;
    foo->say_hi(); // Works well
    foo->say_virtual_hi(); // Crashes the app
    return 0;
}

Puzzle explain

가상 메서드와 비가상 메서드를 호출하는 데 사용되는 다양한 메커니즘으로 인해 혼란이 발생합니다. .

  • 가상 메서드: 호출할 함수를 결정하려면 vtable 조회가 필요합니다. null 포인터에는 연결된 유효한 객체가 없기 때문에 실패합니다.
  • 가상이 아닌 메서드: 직접 컴파일됩니다. 숨겨진 매개변수로 전달된 this 포인터(객체 참조)를 사용하여 함수 호출로.

주어진 코드에서 가상이 아닌 메소드 say_hi()는 널 포인터 역참조 오류를 우회하여 this 포인터를 명시적으로 역참조하지 않습니다. 이는 본질적으로 값으로 전달된 매개변수를 사용하는 함수 호출과 동일합니다.

void Foo_say_hi(Foo* this);

Foo_say_hi(foo);

정의되지 않은 동작

기술적으로는 모든 함수(가상이 아닌 함수도 포함)를 호출합니다. 널 포인터는 C에서 정의되지 않은 동작입니다. 그러나 일부 컴파일러 구현은 위의 비가상 함수 호출과 같은 특정 시나리오에 대해 잘 정의된 동작을 제공할 수 있습니다.

주의

예기치 않은 동작이 보일 수 있지만 편리하지만 이에 의존하는 것은 위험하며 모범 사례가 아닙니다. 널 포인터에서 클래스 멤버에 액세스하는 것은 항상 피하세요. 예상치 못한 결과가 발생할 수 있습니다.

위 내용은 C의 널 포인터에서 비가상 멤버 함수를 호출하는 것이 때때로 작동하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.