2014-02-18 2 views
1
#include <list> 
#include <iostream> 

struct Foo 
{ 
    Foo(int a):m_a(a) 
    {} 
    ~Foo() 
    { 
     std::cout << "Foo destructor" << std::endl; 
    } 
    int m_a; 
}; 

int main() 
{ 
    std::list<Foo> a; 
    Foo b(10); 
    std::cout << &b << std::endl; 
    a.push_back(b); 
    Foo* c = &(*a.begin()); 
    std::cout << c << std::endl; 
    a.erase(a.begin()); 
    std::cout << a.size() << std::endl; 
    c->m_a = 20; 
    std::cout << c->m_a << std::endl; 
    std::cout << b.m_a << std::endl; 
} 

결과는 다음과 같습니다왜 지워진 목록의 개체 멤버 변수에 액세스 할 수 있습니까?

0x7fff9920ee70 
0x1036020 
Foo destructor 
0 
20 
10 
Foo destructor 

내가 더 이상 타르 객체의 멤버 변수를 액세스 할 수 목록에서 개체를 삭제 한 후 나는 보통 생각합니다. 하지만 위의 경우 c->m_a에 액세스 할 수 있습니다. 객체를 지우고 난 후 c이 가리키는 이유는 무엇입니까?

+7

* 정의되지 않은 동작 *을 검색하고 읽으십시오. –

+0

포인터가 여전히 메모리를 가리키고 객체의 구조를 알고 있고 실제로 소멸자가 메모리를 덮어 쓸 수 있다고 생각하기 때문에 상상할 수 있습니다. 그러나 아직 발생하지 않았습니다. – wrossmck

+0

[이 답변] (http : //stackoverflow.com/a/6445794/1782465). – Angew

답변

2

Foo* c = &(*a.begin()); 의도적으로 파괴하는 개체에 대한 포인터를 만들었습니다 (erase() 통해). 그러나 객체에 대한 메모리는 여전히 존재합니다 (이것은 매우 간단한 응용 프로그램이며 OS는 다른 용도로 사용하지 않았기 때문에).

따라서 사용하지 않는 메모리를 더 효과적으로 사용합니다.

+0

@JoachimPileborg 예, 정정 해 주셔서 감사합니다 .... (커피 필요 :)) – fritzone

0

데이터 무결성은 메모리의 해당 부분을 스택이나 새/malloc을 사용하여 힙에 할당 한 경우에만 보장됩니다.

데이터를 일단 해제하면 데이터가 어떻게되는지는 정의되지 않습니다 (구현에 따라 달라짐). 가장 효율적인 메모리 해제 방법은 메모리를 사용 가능으로 표시하고 다른 프로그램에서 malloc을 사용하여 해당 메모리의 일부를 덮어 쓰고 덮어 쓸 때까지 데이터를 남겨 두는 것입니다. 이것이 대부분의 구현이 이것을 어떻게 처리 할 것인가입니다.

C++은 읽고 있거나 쓰는 데이터가 프로그램에 속하는지 여부를 확인하지 않습니다. 따라서 프로그램이 액세스 할 수없는 메모리의 장소에 데이터를 쓰려고 할 때 세그먼트 화 오류가 발생합니다.

귀하의 경우에는 메모리를 비운 다음 즉시 값을 확인하십시오. C++이 행복하게 코드를 실행할 것입니다. 최근에야 해제되었으므로 데이터가 여전히 존재할 확률이 매우 높습니다 (그러나 확실하게 보장되지는 않습니다 : 조만간 덮어 씁니다).

0

야생 세상의 세계에 오신 것을 환영합니다. 정확하게 여기에있는 것은 Dangling Pointer의 경우입니다 (위키 문서를 읽으십시오).

기본적으로 목록에서 항목을 제거한 후 c 포인터가 더 이상 포인터가 아닙니다 (더 이상 점이 아닌 Foo 개체에 대한 포인터입니다). 하지만 여전히 C++에서는이 포인터를 통해 읽고 쓸 수 있지만 부작용은 전혀 결정적이지 않습니다 (아무 일도 일어나지 않을 수도 있음). 코드를 테스트하는 동안 코드가 간단하기 때문에 운좋게도 (또는 이러한 유형의 문제는 오래되어 어려워지고 위험해질 수 있으므로 불행합니다).

+0

그리고 더 큰 프로젝트에서 응용 프로그램 충돌의 근원을 찾는 것이 거의 불가능합니다. – Zaiborg