2013-04-23 2 views
0

I C++에서 다음과 같은 구조를 가지고 :할당 해제 구조

이 MAIN.CPP에서
struct wrapper 
{ 
    // Param constructor 
    wrapper(unsigned int _id, const char* _string1, unsigned int _year, 
     unsigned int _value, unsigned int _usage, const char* _string2) 
     : 
     id(_id), year(_year), value(_value), usage(_usage) 
     { 
      int len = strlen(_string1); 
      string1 = new char[len + 1](); 
      strncpy(string1, _string1, len); 

      len = strlen(_string2); 
      string2 = new char[len + 1](); 
      strncpy(string2, _string2, len); 
     }; 
    // Destructor 
    ~wrapper() 
     { 
      if(string1 != NULL) 
       delete [] string1; 
      if(string2 != NULL) 
       delete [] string2; 
     } 

    // Elements 
    unsigned int  id;   
    unsigned int  year;  
    unsigned int  value;  
    unsigned int  usage; 
    char*   string1;  
    char*   string2; 
}; 

의 내가이 구조의 개체에 대한 메모리를 할당 가정 해 봅시다 :

wrapper* testObj = new wrapper(125600, "Hello", 2013, 300, 0, "bye bye"); 

포인터 연산과 구조 요소 중 하나를 가리키는 포인터를 사용하여 전체 개체를 삭제할 수 있습니까? 이 같은

뭔가 :

void* ptr = &(testObj->string2); 

ptr -= 0x14; 

delete (wrapper*)ptr; 

나 자신을 테스트했습니다 분명히 그것은 작동하지만 난 그 delete testObj에 해당하는 100 % 확실하지 않다.

감사합니다.

+0

은 무엇인가 : 주어진 당신의 유형, 구조 멤버의 이름과 해당 멤버에 대한 포인터를 구조의 기본 주소를 줄 것이다이 매크로를 (내가 ... 내가 알고 ... 알고) 고려 '그림'? –

+1

'testObj'를 지우고 싶다면'delete testObj;'만 쓰면됩니다. –

+0

@ Code-Guru : 프로젝트 코드의 구조 요소였습니다. 나는 그것을 제거했습니다. 죄송합니다 – Daniel

답변

1

포인터 연산과 구조 요소 중 하나를 가리키는 포인터를 사용하여 전체 개체를 삭제할 수 있습니까?

이론적으로는 그렇다.

delete에 지정하는 포인터는 올바른 값을 가져야하며이 값이 기존 포인터 변수에서 왔는지 또는이 방식으로 "조정"하는 것이 중요하지 않습니다.

포인터의 유형도 고려해야합니다. 그 밖의 것이 없다면 산술을 수행하기 전에 char*으로 캐스트하여 단일 바이트 단위로 이동해야합니다. ISO C++ forbids incrementing a pointer of type 'void*' (크기는 void입니다.) 때문에 현재 코드가 컴파일되지 않습니다.

그러나 나는 이 아니고을 추천합니다. 매직 넘버 0x14은 정렬과 패딩 및 구조 변경 가능성으로 인해 신뢰할 수 없습니다.

대신 실제 개체에 대한 포인터를 저장하십시오. 또한 무시 무시한 메모리 혼란으로 멈추고 std::string을 사용하십시오. 현재 복사 생성자가 부족하여 불쾌한 버그가 있습니다.

+0

열린 핵전쟁의 위협 만이 나 같은 모든 상쇄 물체를 시도하도록 설득 할 것입니다. –

+0

@ 마틴 : 여전히 핵전쟁이 바람직하다. 그렇다면 체스 게임은 어떨까요? –

3

기술적으로는,이 같은 코드 (wrapper testObjwrapper* testObj해야 오프셋이 반드시 0x14 아니라고, 예를 들어, 디버그 패드에게 때때로 구조를 구축하고, 어쩌면 다른 세부 내가 놓친 사실을 무시하고) 일 것이다, 그러나 그것은이다 끔찍하고 끔찍한 생각. 나는 그것이 얼마나 무서운지를 충분히 강조 할 수 없다.

0x14 대신 offsetof 매크로를 사용할 수 있습니다.

디버거 회사에서 지출하는 밤을 좋아한다면, 언제든지 그렇게하십시오.

질문의 이유는 포인터 산술을 사용하여 멤버에서 상위로 이동하는 것이 가능하고 실제로 프로덕션 코드에서 수행하려고하는지에 대한 호기심이라고 생각합니다. 나에게 옳다 고 말해줘.

+0

답해 주셔서 감사합니다. 예, 그냥 호기심이라고 말했듯이 :). – Daniel

+0

'기술적으로이 코드는 효과가 없을 것입니다. –

+0

왜 안 되니? 어쩌면 내가 예제에서 뭔가를 놓친 것 같습니다. –

0

포인터 연산과 관련이있다. 여부를 해야 완전히 다른 이야기입니다.

#define ADDRESS_FROM_MEMBER(T, member, ptr) reinterpret_cast<T*>(\ 
    reinterpret_cast<unsigned char *>(ptr) - (ptrdiff_t)(&(reinterpret_cast<T*>(0))->member))