2010-03-09 3 views
7

소프트웨어 회의에서 논의한 바에 따르면 동적으로 할당 된 프리미티브 배열을 일반 delete으로 삭제하면 메모리 누수가 발생하는지 알아보기 위해 알아 보았습니다.delete p입니까? p는 배열에 대한 포인터입니다. 항상 메모리 누수가 있습니까?

내가 비주얼 스튜디오 2008는 윈도우 XP에서 실행을이 작은 프로그램을 작성하고 컴파일

: 작업 관리자는 놀라 울 정도로 메모리가 할당 된 올바르게 해제하여 내 응용 프로그램의 메모리 사용량을 모니터링 I보다

#include "stdafx.h" 
#include "Windows.h" 

const unsigned long BLOCK_SIZE = 1024*100000; 
int _tmain() 
{ 
    for (unsigned int i =0; i < 1024*1000; i++) 
    { 
     int* p = new int[1024*100000]; 
     for (int j =0;j<BLOCK_SIZE;j++) p[j]= j % 2; 
     Sleep(1000); 
     delete p; 
    } 
} 

#include "stdafx.h" 
#include "Windows.h" 


struct aStruct 
{ 
    aStruct() : i(1), j(0) {} 

    int i; 
    char j; 
} NonePrimitive; 

const unsigned long BLOCK_SIZE = 1024*100000; 
int _tmain() 
{ 
    for (unsigned int i =0; i < 1024*100000; i++) 
    { 
     aStruct* p = new aStruct[1024*100000]; 
     Sleep(1000); 
     delete p; 

    } 
} 
: 할당 된 메모리는 꾸준히 '비 원시적 형태의 배열을 할당하는 내 테스트 프로그램을 수정 한

예상대로 증가하지 않았다

10 분 동안 실행 한 후 의미있는 메모리 증가 없음

경고 수준 4로 프로젝트를 컴파일하고 경고가 표시되지 않았습니다.

Visual Studio 런타임에서 할당 된 개체 유형을 추적 할 수 있으므로 해당 환경에 delete과 사이에 차이가 없습니까?

+0

중복? http://stackoverflow.com/questions/1913343/how-could-pairing-new-with-delete-possibly-lead-to-memory-leak-only –

+0

@Philip Potter : 그다지 질문하지 - 그 중 하나는 구체적입니다. 메모리 누출의 원인. 그리고 메모리 누출은 전형적인 경우가 아닙니다. – sharptooth

+0

'shared_ptr '의 배열을 사용해보십시오. 각 배열은 서로 다른 할당 된 int를 가리키고 있습니다. 구현이'delete'와'delete []'를 동일하게 만들고 있는지 알 수 있습니다. 사람들이 알고있는 것들로 C++에서 항상이 매혹은 틀렸다고 분명하게 표준에 명시되어 있지만 때로는 그냥 일하는 것처럼 보입니다 .-) –

답변

19

delete p, 여기서 p는 배열이며 정의되지 않은 동작입니다.

특히, 원시 데이터 형식 (ints)의 배열을 할당하면 컴파일러가 할 일이 많지 않으므로 간단한 malloc()으로 바뀌므로 delete p가 작동 할 수 있습니다.

삭제 p는 실패 할 것입니다, 보통 때

  • p는 복합 데이터 유형이었다 - 페이지 삭제를; 개별 소멸자를 호출하는 것을 알 수 없습니다.
  • "사용자"는 new [] 및 delete [] 연산자를 오버로드하여 일반 힙에 다른 힙을 사용합니다.
  • 디버그 런타임은 new [] 및 delete [] 연산자를 오버로드하여 배열에 대한 추가 추적 정보를 추가합니다.
  • 컴파일러는 추가 RTTI 정보를 개체와 함께 저장해야한다고 결정합니다.이 개체는 p를 삭제합니다. 이해하지 못할 것이지만, [] p를 삭제하십시오; 의지.
17

아니요, 정의되지 않은 동작입니다. 하지 마십시오 - delete[]을 사용하십시오.

VC++ 7-9에서는 when the type in question has trivial destructor이 작동하지만 최신 버전에서는 작동하지 않을 수 있습니다. 정의되지 않은 동작이있는 일반적인 것들입니다. 어쨌든 그것을하지 마십시오. 그것은 정의되지 않은 동작라고

+0

이유에 대한 좋은 설명 @ Eli의 경우에 일하게됩니다! –

2

아니, 당신은 delete[]를 사용한다; 그것은 효과가 있을지 모르지만, 당신은 왜 그런지 모르므로 당신은 그것에 충실하지 않아야합니다.

Visual Studio에서는 배열이나 일반 개체로 개체를 할당 한 방법을 추적하지 않고 마법에 따라 []을 삭제에 추가한다고 생각하지 않습니다. 그것은 아마도 p = new int으로 할당 한 것처럼 동일한 코드에 delete p;을 컴파일하고, 내가 말했듯이, 어떤 이유로 그것이 작동합니다. 그러나 당신은 왜 그런지 모릅니다.

3

배열을 처리 할 때

2

그냥 delete을 사용하면 배열에있는 객체의 소멸자를 호출하지 않습니다. 은 의도 한대로 작동하지만 정확하게 작동하는 방법에는 약간의 차이가 있으므로 정의되지 않습니다. 따라서 사용하지 말아야합니다 (even for built in types).

+0

FAQ에는 매우 강력한 논점이 있습니다. 지적 해 주셔서 감사합니다. – Eli

1

메모리를 누출하지 않는 것처럼 보이는 이유는 삭제가 일반적으로 무료인데, 이는 이미 무료로 필요로하는 메모리 양을 이미 알고 있기 때문입니다. 그러나 C++ 부분은 올바르게 정리되지 않습니다. 첫 번째 객체의 소멸자 만 호출됩니다.

1

[]와 함께 delete를 사용하면 컴파일러에서 배열의 모든 항목에 대해 소멸자를 호출하도록 지시합니다. 이 같은 동적 메모리 할당을 사용하여 객체의 배열에 사용되는 경우 메모리 누수가 발생할 수 있습니다 [] 삭제 사용하지 않는 것은 다음과

class AClass 
{ 
public: 
    AClass() 
    { 
     aString = new char[100]; 
    } 
    ~AClass() 
    { 
     delete [] aString; 
    } 
private: 
    const char *aString; 
}; 

int main() 
{ 
    AClass * p = new AClass[1000]; 
    delete p; // wrong 
    return 0; 
} 
3

한 대답이 호출하지 않기 때문에 네, 그것은 메모리 누수가 발생할 수 있다는 것입니다 배열의 모든 항목에 대한 소멸자. 즉, 배열의 항목이 소유 한 추가 메모리가 누출됩니다.

더 많은 표준 준수 답변은 정의되지 않은 동작입니다. 예를 들어, 컴파일러는 배열이 아닌 항목에 대해 다른 메모리 풀을 사용할 수있는 모든 권한을 가지고 있습니다. 새로운 방법을 사용하지만 다른 것을 삭제하면 힙 손상이 발생할 수 있습니다.

컴파일러는 표준은 지원하지 않지만 첫 번째 문제는 남아 있음을 보증 할 수 있습니다. 추가 메모리 (또는 파일 핸들과 같은 리소스)를 소유하지 않은 POD 항목의 경우에는 괜찮을 수 있습니다.

컴파일러와 데이터 항목이 안전하더라도 어쨌든 사용하지 마십시오. 코드를 읽는 사람도 오해의 소지가 있습니다.

관련 문제