문제

나는 클래스 싱글 블록의 인스턴스로 각 블록마다 간단하고 작업하는 테트리스 게임을 작성했습니다.

class SingleBlock
{
    public:
    SingleBlock(int, int);
    ~SingleBlock();

    int x;
    int y;
    SingleBlock *next;
};

class MultiBlock
{
    public:
    MultiBlock(int, int);

    SingleBlock *c, *d, *e, *f;
};

SingleBlock::SingleBlock(int a, int b)
{
    x = a;
    y = b;
}

SingleBlock::~SingleBlock()
{
    x = 222;
}

MultiBlock::MultiBlock(int a, int b)
{
    c = new SingleBlock (a,b);
    d = c->next = new SingleBlock (a+10,b);
    e = d->next = new SingleBlock (a+20,b);
    f = e->next = new SingleBlock (a+30,b);
}

완전한 라인을 스캔하는 함수가 있으며 관련 블록의 링크 된 블록 목록을 통해 관련된 블록을 삭제하고 다음 포인터를 재 할당합니다.

SingleBlock *deleteBlock;
SingleBlock *tempBlock;

tempBlock = deleteBlock->next;
delete deleteBlock;

게임은 작동하고 블록은 올바르게 삭제되며 모든 것이 예상대로 작동합니다. 그러나 검사 중에도 삭제 된 데이터의 임의 비트에 여전히 액세스 할 수 있습니다.

삭제 한 후 삭제 된 싱글 블록 "x"값 각각을 인쇄하면 일부는 임의의 쓰레기를 반환하고 (삭제를 확인 함) 일부는 222를 반환합니다. Destructor가 실제로 삭제되지 않았음에도 불구하고 나에게 알려줍니다. 힙. 많은 동일한 시험은 항상 제대로 삭제되지 않은 동일한 특정 블록임을 보여줍니다.

결과 :

Existing Blocks:
Block: 00E927A8
Block: 00E94290
Block: 00E942B0
Block: 00E942D0
Block: 00E942F0
Block: 00E94500
Block: 00E94520
Block: 00E94540
Block: 00E94560
Block: 00E945B0
Block: 00E945D0
Block: 00E945F0
Block: 00E94610
Block: 00E94660
Block: 00E94680
Block: 00E946A0

Deleting Blocks:
Deleting ... 00E942B0, X = 15288000
Deleting ... 00E942D0, X = 15286960
Deleting ... 00E94520, X = 15286992
Deleting ... 00E94540, X = 15270296
Deleting ... 00E94560, X = 222
Deleting ... 00E945D0, X = 15270296
Deleting ... 00E945F0, X = 222
Deleting ... 00E94610, X = 222
Deleting ... 00E94660, X = 15270296
Deleting ... 00E94680, X = 222

그 이상의 예상에서 데이터에 액세스 할 수 있습니까?

조금 길다면 죄송합니다.

도움이 되었습니까?

해결책

그 이상의 예상에서 데이터에 액세스 할 수 있습니까?

이것은 기술적으로 정의되지 않은 행동으로 알려져 있습니다. 맥주 캔도 제공해도 놀라지 마십시오.

다른 팁

그 이상의 예상에서 데이터에 액세스 할 수 있습니까?

대부분의 경우 그렇습니다. 삭제를 호출한다고해서 메모리가 제로가되지 않습니다.

동작은 정의되지 않았습니다. 특정 컴파일러를 사용하면 메모리가 제로화 될 수 있습니다. Delete에 전화하면 메모리가 사용 가능한 것으로 표시되므로 다음에 누군가가 새로운, 메모리가 사용될 수 있습니다.

당신이 그것에 대해 생각한다면, 그것은 논리적입니다 - 컴파일러에 더 이상 메모리에 관심이 없다고 말할 때 (사용 삭제), 왜 컴퓨터가 제로화하는 데 시간을 소비해야합니까?

C ++가 정의되지 않은 동작이라고 부르는 것입니다. 데이터에 액세스 할 수 있습니다. 어쨌든, 그것은 잘못된 일입니다.

삭제는 아무것도 삭제하지 않습니다. 메모리를 "재사용을위한 무료"로 표시합니다. 다른 할당 호출이 예약하고 그 공간을 채울 때까지 이전 데이터가 있습니다. 그러나 그것에 의존하는 것은 큰 차이입니다.

이와 관련하여 라이브러리에서 종종 발생하는 관행 중 하나는 삭제 기능입니다.

template< class T > void Delete( T*& pointer )
{
    delete pointer;
    pointer = NULL;
}

이것은 실수로 유효하지 않은 메모리에 액세스하지 못하게합니다.

전화해도 괜찮습니다 delete NULL;.

힙 메모리는 많은 블랙 보드와 같습니다. 당신이 선생님이라고 상상해보십시오. 당신이 당신의 수업을 가르치는 동안, 칠판은 당신에게 속하며, 당신은 당신이하고 싶은 모든 일을 할 수 있습니다. 당신은 그것에 낙서하고 원하는대로 물건을 덮어 쓸 수 있습니다.

수업이 끝나고 방을 떠나려고 할 때, 블랙 보드를 지우는 데 필요한 정책은 없습니다. 당신은 일반적으로 당신이 쓴 것을 볼 수있는 다음 교사에게 블랙 보드를 건네줍니다.

시스템은 메모리를 통해 메모리를 지우지 않습니다. delete(). 따라서 내용은 재사용 및 덮어 쓰기를 위해 메모리가 할당 될 때까지 여전히 액세스 할 수 있습니다.

삭제 삭제 거래는 메모리를 처리하지만 메모리를 수정하거나 제로화하지는 않습니다. 여전히 거래 된 메모리에 액세스해서는 안됩니다.

객체를 삭제 한 후에는 메모리의 내용에 어떤 일이 발생하는지 정의되지 않습니다. 그것은 그 메모리가 무료로 재사용 할 수 있음을 의미하지만, 구현은 원래있는 데이터를 덮어 쓸 필요가 없으며 즉시 메모리를 재사용 할 필요가 없습니다.

객체가 사라진 후에 메모리에 액세스해서는 안되지만 일부 데이터가 그곳에 남아 있어야합니다.

아직 메모리를 0/변경하지는 않지만 ... 어느 시점에서 깔개는 발 아래에서 당겨 질 것입니다.

아니요는 확실히 예측할 수 없습니다. 메모리 할당/거래가 얼마나 빨리 휘젓는 지에 따라 다릅니다.

예, 때때로 예상 될 수 있습니다. 반면 new 데이터를위한 공간을 보유하고 delete 단순히 생성 된 포인터를 무효화합니다 new, 이전에 예약 된 위치에서 데이터를 작성할 수 있습니다. 반드시 데이터를 삭제하는 것은 아닙니다. 그러나 해당 위치의 데이터가 언제든지 변경 될 수 있으므로 프로그램이 잘못 행동 할 수 있기 때문에 해당 동작에 의존해서는 안됩니다. 이것이 당신이 사용한 후에는 이유입니다 delete 포인터에 (또는 delete[] 배분 된 배열에서 new[]), 당신은 메모리를 사용하여 메모리를 할당하지 않는다고 가정 할 때 유효하지 않은 포인터를 변조 할 수 없도록 null을 할당해야합니다. new 또는 new[] 그 포인터를 다시 사용하기 전에.

정의되지 않은 동작으로 이어지고 거래를 삭제하여 메모리를 삭제하여 0으로 다시 연결하지 않습니다.

0을 제로 만들려면 다음을 수행하십시오.

SingleBlock::~SingleBlock()

{    x = y = 0 ; }

런타임 이이 오류를보고하지 않을 수 있지만 Valgrind와 같은 적절한 오류 확인 런타임을 사용하면 메모리가 해제 된 후 메모리 사용을 경고합니다.

코드를 작성하는 경우 권장합니다 new/delete 그리고 원시 포인터 (가 아니라 std::make_shared() 그리고 유사하게, 당신은 Valgrind에서 단위 테스트를 수행하여 최소한 그러한 오류를 발견 할 가능성이 있습니다.

글쎄, 나는 이것에 대해 꽤 오랫동안 궁금해하고 있었고, 나는 후드 아래에서 무슨 일이 일어나고 있는지 더 잘 이해하기 위해 시험을 실행하려고 노력했다. 표준 답변은 전화 후 삭제 그 메모리 지점에 액세스 할 때 좋은 것을 기대해서는 안됩니다. 그러나 이것은 나에게 충분하지 않은 것처럼 보였다. 전화 할 때 실제로 무슨 일이 일어나고 있습니까? 삭제 (ptr)? 여기 내가 찾은 것이 있습니다. Ubuntu 16.04에서 G ++를 사용하고 있으므로 결과에서 역할을 할 수 있습니다.

삭제 연산자를 사용할 때 처음 기대 한 것은 해당 메모리가 다른 프로세스에서 사용을 위해 시스템으로 되돌아 갈 것이라는 것입니다. 내가 말 해주세요 이것은 일어나지 않습니다 내가 시도한 상황에서.

메모리가 출시되었습니다 삭제 여전히 프로그램에 할당 된 것 같습니다. 새로운. 나는 시도했지만 전화 후 메모리 사용량이 감소하지 않습니다. 삭제. 나는 약 30MB의 목록을 완료 한 소프트웨어를 가지고있었습니다. 새로운 전화를 한 다음 후속으로 공개했습니다 삭제 전화. 일어난 일은 프로그램이 실행되는 동안 시스템 모니터를보고, 심지어 긴 수면 이후 삭제 전화, 메모리 소비 내 프로그램은 동일했습니다. 감소하지 않습니다! 이것은 그것을 의미합니다 삭제 시스템에 메모리를 해제하지 않습니다.

사실, 그것은 프로그램에 의해 할당 된 기억이 그의 영원한 것처럼 보인다! 그러나 요점은 거래를 처리하면 더 이상 할당하지 않고도 동일한 프로그램으로 메모리를 다시 사용할 수 있다는 것입니다. 나는 15MB를 할당하여 해방 한 다음 다른 15MB의 데이터를 할당하려고 시도했으며 프로그램은 30MB를 사용하지 않았습니다. 시스템 모니터는 항상 약 15MB를 보여주었습니다. 이전 테스트와 관련하여 내가 한 일은 절반 할당, 절반 거래, 할당의 절반과 같은 일이 일어난 순서를 변경하는 것입니다.

그래서, 분명히 프로그램에서 사용되는 메모리는 증가 할 수 있지만 절대 줄어들지 않습니다.. 더 이상 메모리가 없을 때와 같은 중요한 상황에서 다른 프로세스에 대해 메모리가 실제로 출시 될 것이라고 생각했습니다. 결국, 다른 프로세스가 그것을 요구할 때 프로그램이 자신의 기억을 영원히 유지하게하는 것은 어떤 의미가 있습니까? 그래서 나는 30MB를 다시 할당했다 그들을 처리하는 동안 나는 a memtester 물리적 기억만으로도 할 수 있습니다. 나는 내 소프트웨어가 메모리를 Memtester에 나눠 줄 것으로 예상했다. 그러나 그것을 추측하십시오, 그것은 일어나지 않았다!

나는 행동을 보여주는 짧은 스크린 캐스트를 만들었습니다.

Delete example memory

정직하게 100%, 상황이있었습니다. 무엇 일어난. 내 프로그램의 거래 프로세스 중에 사용 가능한 물리적 메모리보다 더 많은 Memtester를 시도했을 때, 내 프로그램에서 사용한 메모리는 약 3MB로 떨어졌습니다. Memtester 프로세스는 자동으로 죽었고 일어난 일은 훨씬 더 놀라운 일이었습니다! 내 프로그램의 메모리 사용량은 각 삭제 호출마다 증가했습니다! 마치 Ubuntu가 Memtester 사건 이후 모든 기억을 되찾고있는 것처럼 보였습니다.

가져 왔습니다 http://www.thecrowned.org/c-delete-operator-really-frees-memory

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top