2010-11-27 2 views
5

운영자가 새로 작동하지만 삭제를 호출하자마자 free (ptr) 라인에서 충돌합니다. 어느 누구든지이 기본 클래스에서 연산자 new를 오버로드하고 삭제할 때 내가 잘못하고있는 것을 말할 수 있습니까? 힌트 : 나는 디자인 문제에 대해 묻지 않는다.운영자가 힙 손상으로 인해 힙 손상을 일으켰습니다. 새로운 작업이 매우 편리합니다.

class Base { 
private: 
    int i; 

public: 
    Base() : i (10) { 
    } 

    static void * operator new (size_t size) { 
     if (size = 0) size = 1; // please read this line carefully! size = 0! 
     return malloc (size); 
    } 

    static void operator delete (void *ptr, size_t size) { 
     if (ptr == NULL) return; 
     free (ptr); 
    } 
}; 
+1

두 번 개체를 삭제 또는'new'를 호출 얻을 수없는 포인터를 통해 개체를 삭제하려고합니까? –

+0

부수적으로,'free (NULL)'은 안전하다는 것을 보장한다. (아무 것도하지 않는다.) 그래서 특별한 경우는 필요 없다. –

+0

hm ... 나쁘다 : 만약'if (size == 0)'을'if (size = 0)'로 바꾸고 생성자뿐만 아니라 private 데이터 멤버를 추가하면 코드는 실패 할 것이다. 나는'size = 0'은 발생해서는 안되지만 생성자에서이 클래스의 private 데이터 멤버를 초기화 할 때만 코드가 실패하는 버그라는 것을 알고 있습니다. – Jaywalker

답변

4

이 나를 위해 작동합니다

#include <cstdlib> 
using namespace std; 
class Base { 
public: 
    void * operator new(size_t size) { 
     if (size == 0) size = 1; 
     return malloc (size); 
    } 

    void operator delete (void *ptr, size_t size) { 
     if (ptr == NULL) return; 
     free (ptr); 
    } 
}; 

int main() 
{ 
    Base* b = new Base; 
    delete b; 
    return 0; 
} 

[email protected]:/tmp$ g++ -o test test.cpp 
[email protected]:/tmp$ ./test 
[email protected]:/tmp$ valgrind ./test 
==7229== HEAP SUMMARY: 
==7229==  in use at exit: 0 bytes in 0 blocks 
==7229== total heap usage: 1 allocs, 1 frees, 1 bytes allocated 
==7229== 
==7229== All heap blocks were freed -- no leaks are possible 
==7229== 
==7229== For counts of detected and suppressed errors, rerun with: -v 
==7229== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 
+0

감사합니다. 예, 코드가 정상입니다. 내 코드에서 몇 가지 추가 변경 작업을 수행했습니다. 당신은 그것에 대해 논평 할 수 있습니까? – Jaywalker

1

난 당신이 준 샘플 코드와 어떤 문제가 표시되지 않습니다.

다음 작품은 정상적으로 작동합니다.

[email protected] ~ $ cat leak_check.cpp && g++ leak_check.cpp && valgrind --leak-check=full ./a.out 
#include <cstdlib> 
class Base { 
public: 
    static void * operator new (size_t size) { 
     if (size == 0) size = 1; 
     return malloc (size); 
    } 

    static void operator delete (void *ptr, size_t size) { 
     if (ptr == NULL) return; 
     free (ptr); 
    } 
}; 

int main() 
{ 
    Base * p = (Base *) Base::operator new(sizeof(Base)); 
    Base::operator delete((void*)p,sizeof(Base)); 
} 
==4561== Memcheck, a memory error detector 
==4561== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==4561== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info 
==4561== Command: ./a.out 
==4561== 
==4561== 
==4561== HEAP SUMMARY: 
==4561==  in use at exit: 0 bytes in 0 blocks 
==4561== total heap usage: 1 allocs, 1 frees, 1 bytes allocated 
==4561== 
==4561== All heap blocks were freed -- no leaks are possible 
==4561== 
==4561== For counts of detected and suppressed errors, rerun with: -v 
==4561== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 17 from 6) 

NULL 포인터를 비우는 것은 완벽합니다.

free 함수는 공간, 즉 상기 할당에 이용 가능하게 ptr가 해제 될 가리키는시킨다. ptr이 널 포인터 인 경우, 조치가 발생하지 않습니다..

그래서 if (ptr == NULL) return;은 생략 할 수 있습니다.

2

실제 문제는 new도 아니고 delete 연산자도 아닙니다. 당신의 구현은 매우 간단합니다. 여기에는 아무런 문제가 없습니다.

실제 문제는 힙 손상입니다. 이는 코드에 의해 야기 되었기 때문에 반드시 Base 개체를 조작하는 코드 일 필요는 없습니다. delete 개체를 찾을 때 힙 손상이 발견되는 것입니다.

아마 delete 개체 전에 힙 손상을 수행하는 코드가 있습니다.

잘못된 메모리 액세스에 대한 코드를 확인해야합니다. 여기에는 다음이 포함

  1. 당신이
  2. 당신이 그것을 확보 한 후 메모리를 사용하지 않는 확인 할당 된 것보다 더 많은 메모리에 액세스하지 않습니다 보장.