2016-06-18 9 views
0

그렇다면 두 개의 프로그램을 배치 할 것입니다. 두 가지 모두 포인터와 새 연산자를 사용하는 동적 배열입니다. 그러나 삭제 연산자가 마음에 들지 않는 것 같습니다.C++ 포인터 및 동적 배열 및 삭제 연산자

#include <iostream> 
int main() 
{ 
    int *p; 
    p = new int[5]; 

    for (int i = 0; i < 5; i++) 
    { 
    p[i] = 25 + (i * 10); 
    std::cout << p[i] << " "; 
    } 
    std::cout << std::endl; 

    delete [] p; 
    p = NULL; 

    return 0; 
} 

이것이 첫 번째 프로그램입니다. 그것은 삭제 연산자를 좋아한다. 이제 삭제 연산자를 싫어하는 프로그램 :

#include <iostream> 
int main() 
{ 
    int x; 
    int *p; 
    p = new int[5]; 

    *p = 4; 

    for (int i = 0; i < 5; i++) 
    { 
    std::cout << *p << " "; 
    x = *p; 
    p++; 
    *p = x + 1; 
    } 
    std::cout << std::endl; 

    delete [] p; 
    p = NULL; 

    return 0; 
} 

이 프로그램은 정상적으로 컴파일됩니다. 그러나 실행 중에는 에러 주소 -free(): invalid pointer: 0xfdb038 .. 또는 특정 실행을위한 메모리 주소가 무엇이든간에 throw됩니다. 따라서 질문은 다음과 같습니다. 두 번째 경우에 삭제 연산자를 사용할 수없는 이유는 무엇입니까? 나는 메모리 누출을 원하지 않는다; 나는 포인터가 매달려있는 것을 원하지 않는다. 방금 ​​p = NULL;라고 말하면 p = 0이지만 포인터가 여전히 매달려 있다고 생각합니까?,하지만 확실하지 않습니다. 미리 감사드립니다. 코드의 두 번째 조각이 루프에서

+2

두 번째 경우에는 'p'포인터를 변경하고 삭제하기 전에 배열 시작을 가리 키지 않기 때문에. –

답변

2

봐 :이 줄, 현재 p가 가리키는 메모리 주소에 기록 할 것으로

for (int i = 0; i < 5; i++) 
{ 
    std::cout << *p << " "; 
    x = *p; 
    p++; 
    *p = x + 1; // <--- Here 
} 

알 수 있습니다. 항상 p을 증가시키고 쓰기 때문에 p에 할당 된 지역의 끝을 지나면 쓸어 버리게됩니다. (pOrig을 포인터로 사용하여 p이 처음으로 가리킨다 고 가정하면이 포인터는 pOrig[1], pOrig[2], pOrig[3], pOrig[4]pOrig[5]에 기록되며 마지막 쓰기는 영역 끝을 지나치게됩니다. 결과적으로 정의되지 않은 동작이 발생하므로 문자 그대로 아무 것도 발생할 수 없습니다. 이것은 나쁜 소식입니다.

또한 delete[]은 사용자가 할당 한 배열의 첫 번째 요소에 대한 포인터를 전달한다고 가정합니다. 그 루프에서 p이 여러 번 증가했기 때문에 delete[]에 할당 된 배열의 기본이 아닌 포인터가 있으므로이 문제가 발생합니다.

수정하려면 p을 증가시킨 후 new[]으로 할당 된 원래 배열에 포인터를 저장하여 수정 된 포인터 p 대신이 포인터를 해제 할 수 있도록하십시오.

0

new에서 가져온 포인터는 delete이어야합니다. 그러나 두 번째 코드에서는 포인터를 변경 한 p++을 수행했습니다. 따라서 newdelete에서 가져 오지 못한 포인터가 delete에 충돌했습니다.

이 오류 유형을 수정하려면 new을 사용하지 마십시오. 대신 std::vector<int> p;을 사용하십시오. new을 필요로하지 않으므로 delete을 잊지 마세요.

+2

"이런 유형의 오류를 고치려면 결코 새로운 것을 사용하지 마십시오."- 이상한 조언 ... –

+3

@EdgarRokyan 어떻게 이상합니까? 현대 C++에서 수동 메모리 관리를 찾지 못할 것입니다.이 오류가 발생하기 쉽고 구식이며 불필요한 실습을받을 필요가 없습니다. – nwp

+0

@EdgarRokyan 실제로 현대 C++에서는 명백한'new'와'delete' 연산자를 피하는 경향이 있습니다. 예를 들어, 스마트 포인터 타입과 함께'make_shared'와'make_unique'를보십시오. – templatetypedef

0

p이 (가) p++으로 변경됩니다. 원본 포인터를 저장하려면 항상 삭제해야합니다. 이와 같이 :

#include <iostream> 
int main() 
{ 
    int *original = new int[5]; 
    int *p = original; 

    for (int i = 0; i < 5; i++) 
    { 
    std::cout << *p << " "; 
    int x = *p; 
    p++; 
    *p = x + 1; 
    } 
    std::cout << std::endl; 

    delete [] original;  
    return 0; 
}