2017-11-10 16 views
0

아래 제공된 예제는 다소 나쁜 패턴이지만 나는이 질문을 호기심에서 물어보고 싶습니다. 이 상황에서메모리 블록을 수동으로 덮어 쓴 경우 구조체 배열을 삭제하는 방법

은 : packets 파괴시가 (메모리가 제로로 덮어되었다)을 MyStruct's 가상 테이블의 소멸자를 찾을 수 없기 때문에

int main (int argc, char **argv) { 
    struct MyStruct { 
     virtual ~MyStruct() = default; 
     int dummyField; 
    }; 
    int numpack = 1000; 
    int memoryBlockSize = numpack*sizeof(MyStruct); 
    char* buf = new char[memoryBlockSize]; 
    memset(buf, 0, memoryBlockSize); 
    { 
     MyStruct packets[numpack]; 
     memcpy(&packets, buf, memoryBlockSize); 
    } // segmentation fault on scope exit 
    MyStruct* packets = new MyStruct[numpack]; 
    memcpy(packets, buf, memoryBlockSize); 
    delete[] packets; // segmentation fault on delete attempt 
    delete[] buf; 

    return 0; 
} 

세그먼트 오류가 예상된다. 그런 경우 packets이 가리키는 메모리 블록을 정상적으로 삭제할 수 있습니까?

삭제 기능에 (포인터 + 블록 크기)를 제공 할 가능성이 있습니까?

아니면 내가 같은 방식으로 할당 된 다른 메모리 블록에서 메모리를 복사하여 packets가 가리키는 블록 복구를 시도 할 수 있습니다 (하지만 가상 테이블의 포인터는 메모리에서 다른 장소를 가리 킵니다) :

MyStruct* anotherPackets = new MyStruct[numpack]; 
memcpy(packets, anotherPackets, memoryBlockSize); 
+1

정의되지 않은 동작이 많이 발생합니다.이를 수정하는 표준 방법이 없습니다. – Barmar

+0

'무료 (패킷)'시도 – user5821508

+0

시도했습니다. 결과는 다음과 같습니다.''free() : invalid pointer '' – Ptaq666

답변

1

MyStruct에 따라 다릅니다. 예를 들어 비어 있지 않은 std::string 개체가 포함되어 있기 때문에 비 단순한 소멸자가있는 경우 개체를 지울 때 문자열 문자로 메모리 누수가 발생하기 때문에 손실 된 것입니다. 하위 객체에 따라 상황이 더욱 악화 될 수 있습니다.

그러나 당신이 필요로하는 모든 packets이 범위를 벗어나 갈 때 소멸자가 성공적으로 호출 할 수 있다는 것입니다, 당신은 단순히 (신규) 구성하기 위해 새로 만들기 배치을 사용하여 배열 내부 오브젝트 수 있습니다

{ 
    MyStruct packets[numpack]; 
    memcpy(&packets, buf, memoryBlockSize); 
    for (int i=0; i<numpack; i++) { 
     new(packets+i) MyStruct(); // re-creates an object 
    } 
} // the new objects are being destructed here 

그러나 소멸자가 초기 객체에서 호출되지 않았으므로 그로 인해 어떤 것도 발생할 수 있습니다 (즉, 정의되지 않은 동작이 의미하는 것 ...). 따라서 을 실제 코드에서 절대로 사용하지 마십시오.

+1

소멸자는 '가상'이기 때문에 이미 중요하지 않습니다. "사소한 소멸자"의 개념은 C 호환 유형에 C++ 소멸자가있는 것처럼 가장하는 허구입니다. 또한, for (i = 0; i! = numpack; ++ i) (packets + i) -> ~ MyStruct'를 사용하면 초기 객체에 소멸자를 호출 할 수 있습니다. 그것은 UB를 수정합니다. – MSalters