2012-02-24 4 views
1

에 의해 스택에서 개체를 반환 내가 값을 반환 : 메모리 누수를 얻을 수있는 기회가 있습니다

string get() 
{ 
    string str("hello"); 
    return str; 
} 

? 몇 가지 예를 보여 드리겠습니다 :

int main(int argc, char** argv) 
{ 
    string str=get(); // case 1 
    get();    // case 2 
    string* ptr=&get(); // case 3 
} 

어떤 경우에 메모리 누수가 발생합니까?

+2

왜 메모리 누수가 있다고 생각합니까? – tenfour

+0

get()의 str이 힙에 할당되지 않았으므로 스택에 있습니다. 하지만 값을 반환 할 때 할당의 왼쪽 피연산자로 개체의 복사본이 있습니다. 특히 왼쪽 피연산자가없는 경우 (사례 2)에는이 개체가 복사 된 위치를 알 수 없으므로 삭제됩니다 ? –

+0

@RamyAlZuhouri : 경우 2에서 반환 된 개체는 * 임시 *이며 식 끝에서 삭제됩니다. –

답변

7

메모리 누수가 없지만 경우 3은 막연하게 유효하지 않습니다.

std::string은 포인터 또는 다른 것이 아니기 때문에 get() 함수는 문자열의 복사본을 반환합니다. 이는 사용자의 관점에서 함수에서 int을 반환하는 것과 거의 동일합니다. 복사본이 만들어지고 반환되며 할당 또는 사용이 가능하도록 함수 범위 외부에서 유효합니다. 이 동작이 없으면 일반적으로 반환 값을 사용할 수 없습니다.

POD와 클래스에 매우 유사합니다 (클래스에는 복사 생성자가 필요하지만). 거의 모든 std 클래스에 대해이 작업을 수행 할 수 있어야하지만 사본을 만드는 데 소요되는 비용은 다양합니다 (예 : std::vector<BigClass>(1000)을 반환하는 것은 좋지 않습니다). 설정에 따라 컴파일러는 RVO를 통해 복사본을 최적화 할 수 있습니다.

사례 1 : 사본이 str으로 할당되었으므로 메모리 누수가 발생하지 않으며 문제가되지 않습니다. 아주 간단합니다.

사례 2은 사본을 폐기하지만 여전히 문제가 없습니다.

사례 3 신속하게 (때문에 사용하지 않는 것에) 컴파일러에 의해 파괴 될 것이다 임시 반환 값의 주소를 가지고 ptr 매달려 포인터를 만들려고합니다. 임시 사용이 종료 된 후 ptr을 사용하면 정의되지 않은 동작이 발생하며 이는 아마도 액세스 위반 일 수 있습니다. 임시가 파괴되는 장소와시기는 컴파일러, 설정 및 신뢰할 수없는 기타 사항에 따라 다릅니다.

도 유효하지만 그다지 유용하지는 않지만 올바른 형식입니다.

+0

3 번이 맞지 않습니다. – GWW

+0

케이스 3이 컴파일되지 않는 것이 맞다고 생각하지만 잘못된 이유 때문입니다. –

+0

나는 downvote를하지 않았지만'3'을 좀 더 설명 할 수 있습니까? – Muggen

2

동적으로 힙에 메모리를 할당하지 않으므로 (new 또는 malloc 및 친구들 사용) 누락 된 예제가 없습니다.

+0

이것은 생성하려는 클래스가 적절한 소멸자를 가지고 있다고 가정합니다.) – GWW

+1

나는 그것을 추가하는 것에 대해 생각했지만, OP가 자신의 문자열 클래스를 굴리지 않았다고 가정하기 때문에 세부 사항을 생략했습니다. 'new' 또는'malloc'을 포함하는 코드를 작성하면 호출자가 파기를 담당하거나 호출자가 객체의 소유권을 갖는다는 것을 명확하게 문서화 한 것을 인식하는 것이 중요합니다. – Joe

+0

@GWW : 규칙은 재귀 적으로 적용됩니다. 클래스가'new'도 사용하지 않으면 클래스 자체도 누출되지 않습니다. – MSalters

1

std 클래스와 단순한 유형의 경우 누출되지 않아야합니다. 세관 클래스의 경우 내부 리소스를 올바르게 올바르게 할당하고 할당을 해제하는 클래스를 만드는 것은 사용자의 몫입니다.