ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Effective C++] 3장(2) - 자원 관리
    쾌락없는 책임 (공부)/Effetive C++ 요약본 2022. 3. 13. 17:11
    반응형
    본 카테고리는 프로텍 미디어의 '이펙티브 C++'을 보고 요약하는 카테고리입니다.

    3판을 기준으로 하며 전체 내용이 아닌 간략한 내용만을 요약하고 있습니다.

     

    항목 16 : new 및 delete를 사용할 때는 형태를 반드시 맞추자!

    std::string *stringArray = new strd::string[100];
    ...
    delete stringArray;

     딱 보면 이상한 코드입니다. 이러면 이후 99개의 string들이 delete될 수 없습니다.

     new 키워드로 동적 할당을 하면 아래 메모리 할당, 할당된 메모리에 대해 한개 이상의 생성자가 호출 됩니다. delete 표현식에서는 다른 2가지 내부 동작을 하게 됩니다. 할당된 메모리에 대해 한 개 이상의 소멸자 호출, 메모리 해제.

     여기서 삭제되는 포인터는 객체 한개를 가리킬까요 아님 연결된 배열을 가리킬까요? 일단 new 로 힙에 만들어진 단일 객체 메모리 구조는 스택의 구조와 다릅니다!

    그래서 배열을 삭제할 때는 꼭 []을 붙여야 합니다.

     

     또한 typedef로 지정된 타입들에도 같은 일을 해줘야 합니다.

    typedef std::string Address[4];
    
    std::string *pal = new Address[4];
    ...
    delete pal;     // 무슨 일이 생길지 모른다!
    delete [] pal;  // 음 좋고

     그리고 가급적 typedef로 배열을 가리지 않는게 좋습니다! 또한 STL에 좋은 컨테이너들이 많이 있으므로 이걸 사용해보도록 합시다.

     

    항목 17 : new 로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 하자

     Widget 객체에 우선순위를 조정해주는 함수가 있다고 합시다.

    int priority();
    void processingWidget(std::tr1::shared_ptr<Widget> pw, int priority);
    ...
    processWidget(new Widget, priority());

     그런데 위 processWidget(new Widget, priority());는 컴파일이 되지 않습니다. 왜냐면 함수는 shared_ptr이 필요한데 넣은건 원시 포인터니깐요.

    processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());

     일단 위 코드는 컴파일이 되는데 문제가 하나 있습니다! 여기서 자원을 흘릴 가능성이 있기 때문이죠. 왜 자원을 흘린다는건지 아래에서 알아보겠습니다.

     

     일단 함수 processWidget에서는 인자들을 평가하는데 여기서 첫번째 인자는 2부분으로 나뉘게 됩니다.

    - new Widget 실행

    - tr1::shared_ptr의 생성자 호출

    그래서 컴파일러는 함수 호출 전 위 2개 + priority 함수를 호출해야 하는데 여기서 문제가 3가지의 실행 순서가 컴파일러마다 다르다는 것입니다. (C#에서는 고정이라고 합니다) 그래서 만약 priority 함수 호출이 2번째가 된다면 new Widget은 포인터 소실이 될 가능성이 있습니다. 그래서 tr1::shared_ptr에 저장하기도 전 예외가 발생하는 것이죠.

    ( 자원 생성 시점과 자원이 자원관리 객체로 넘어가는 시점에 예외가 끼어들 수 있어서)

    // new 로 생성한 객체를 스마트 포인터에 담는 문장을 하나로 저장
    std::tr1::shared_ptr<Widget> pw(new Widget); 
    
    processWidget(pw, priority());  //  해결 완료

     그래서 이런 식으로 저장을 먼저 한 뒤 함수 호출을 해주면 문제가 해결됩니다.

    반응형

    댓글

Designed by Tistory.