[c++] malloc과 new를 어떤 경우에 사용합니까?


Answers

간단한 대답은 : C ++에 malloc 을 사용하지 말고 정말 그렇게해야합니다. malloc 은 C ++과 함께 사용할 때 많은 결함이 있습니다.이 new 은 극복하기 위해 정의되었습니다.

C ++ 코드에 대한 결함으로 수정되었습니다.

  1. malloc 은 의미있는 방식으로 타입 안전하지 않습니다. C ++에서는 void* 에서 반환 값을 캐스팅해야합니다. 이로 인해 잠재적으로 많은 문제가 발생합니다.

    #include <stdlib.h>
    
    struct foo {
      double d[5];
    }; 
    
    int main() {
      foo *f1 = malloc(1); // error, no cast
      foo *f2 = static_cast<foo*>(malloc(sizeof(foo)));
      foo *f3 = static_cast<foo*>(malloc(1)); // No error, bad
    }
    
  2. 그것은 그것보다는 더 나쁘다. 문제의 유형이 POD (평범한 구 데이터) 인 경우 f2 가 첫 번째 예에서와 같이 반 정량적으로 malloc 을 사용하여 메모리를 할당 할 수 있습니다.

    유형이 POD인지는 분명하지 않습니다. 특정 유형이 결과적으로 컴파일러 오류가없고 잠재적으로 디버그 문제가 발생하지 않는 POD에서 비 POD로 변경 될 수 있다는 사실은 중요한 요소입니다. 예를 들어, 누군가 (아마도 다른 프로그래머가 유지 보수하는 동안 나중에 foo 가 더 이상 POD가되지 않게하는 변경을하면 컴파일 타임에 명백한 오류가 나타나지 않을 것입니다. 예를 들면 다음과 같습니다.

    struct foo {
      double d[5];
      virtual ~foo() { }
    };
    

    f2malloc 도 명백한 진단없이 악화 될 것입니다. 여기 예제는 간단하지만, POD가 아닌 멤버를 추가하여 비 PODness를 훨씬 더 멀리 가져올 수 있습니다 (예 : 기본 클래스). C ++ 11 / boost가있는 경우 is_pod 를 사용하여이 가정이 올바른지 확인하고 그렇지 않은 경우 오류를 생성 할 수 있습니다.

    #include <type_traits>
    #include <stdlib.h>
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      return static_cast<foo*>(malloc(sizeof(foo)));
    }
    

    boost가 C ++ 11 또는 다른 컴파일러 확장이 없는 유형이 POD인지 여부를 판별 할 수없지만 .

  3. 할당이 실패하면 mallocNULL 리턴한다. new std::bad_alloc 을 던질 것이다. 나중에 NULL 포인터를 사용하는 동작은 정의되지 않습니다. 예외가 Throw되었을 때 예외가 발생하고 오류의 원인에서 예외가 발생합니다. 모든 호출에서 적절한 테스트를 통해 malloc 을 래핑하는 것은 지루하고 오류가 발생하는 것처럼 보입니다. (좋은 일을 모두 취소하기 위해서는 한 번만 잊어 버려야합니다.) 호출자가 현명하게 처리 할 수있는 수준으로 예외를 전파 할 수있는 예외가 허용 될 수 있습니다. 여기서 NULL 은 의미있게 전달하기가 훨씬 어렵습니다. 우리는 safe_foo_malloc 함수를 확장하여 예외를 던지거나 프로그램을 종료하거나 핸들러를 호출 할 수 있습니다.

    #include <type_traits>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      static_assert(std::is_pod<foo>::value, "foo must be POD");
      foo *mem = static_cast<foo*>(malloc(sizeof(foo)));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return mem;
    }
    
  4. 근본적으로 malloc 은 C 기능이며 new 기능은 C ++ 기능입니다. 결과적으로 malloc 은 생성자와 잘 작동하지 않으므로 바이트 청크 만 할당합니다. 우리는 safe_foo_malloc 더 확장하여 배치 new 것을 사용할 수 있습니다 :

    #include <stdlib.h>
    #include <new>
    
    void my_malloc_failed_handler();
    
    foo *safe_foo_malloc() {
      void *mem = malloc(sizeof(foo));
      if (!mem) {
         my_malloc_failed_handler();
         // or throw ...
      }
      return new (mem)foo();
    }
    
  5. 우리의 safe_foo_malloc 함수는 매우 일반적이지 않습니다. foo 뿐만 아니라 모든 유형을 처리 할 수있는 무언가가 필요합니다. 기본이 아닌 생성자에 대한 템플릿과 가변 템플릿을 사용하여이 작업을 수행 할 수 있습니다.

    #include <functional>
    #include <new>
    #include <stdlib.h>
    
    void my_malloc_failed_handler();
    
    template <typename T>
    struct alloc {
      template <typename ...Args>
      static T *safe_malloc(Args&&... args) {
        void *mem = malloc(sizeof(T));
        if (!mem) {
           my_malloc_failed_handler();
           // or throw ...
        }
        return new (mem)T(std::forward(args)...);
      }
    };
    

    지금까지 우리가 지금까지 확인한 모든 문제를 수정하면서 실제적으로 기본 new 연산자를 재발 명했습니다. malloc 과 placement new 를 사용한다면 new 를 사용하면됩니다!

Question

C ++에서 여러 가지 방법으로 데이터를 할당하고 해제 할 수 있다는 것을 알았습니다. malloc 을 호출 할 때 free 호출해야하며 new 연산자를 사용하면 delete 와 쌍을 이루어야하며 두 가지를 혼합하는 실수라고 이해합니다 (예 : free() 호출 free() new 연산자로 만든 무언가에 대한),하지만 malloc / free 사용해야 할 때 및 내 실제 프로그램에서 new / delete 사용해야 할 때 명확하지 않다.

C ++ 전문가라면이 점에 대해 알고있는 규칙이나 규칙을 알려주십시오.




C ++로 포팅 할 C 코드가 있다면, malloc () 호출을 그 안에 남겨 둘 수 있습니다. 모든 새로운 C ++ 코드에 대해 new를 대신 사용하는 것이 좋습니다.




새로운 vs malloc ()

1) new연산자 이고 malloc()함수 입니다.

2) malloc()new 호출 생성자 입니다.

3) new정확한 데이터 타입을 반환하고, malloc()void *를 반환합니다.

4) newmalloc() 이 NULL을 리턴하는 동안 NULL을 반환하지 않습니다 (실패시 throw합니다).

5) malloc() 처리하는 동안 new 의해 처리되지 않는 메모리 재 할당




malloc ()은 C에서 메모리를 동적으로 할당하는 데 사용되는 반면 c ++에서는 new ()가 동일한 작업을 수행합니다. 따라서 2 개 국어의 코딩 규칙을 혼용 할 수는 없습니다. calloc과 malloc () 사이의 차이점을 물으면 좋겠다.




new 는 구조체의 기본값을 초기화하고 그 내부의 참조를 올바르게 링크합니다.

예 :

struct test_s {
    int some_strange_name = 1;
    int &easy = some_strange_name;
}

그래서 new struct test_s 는 작업 참조가있는 초기화 된 구조체를 반환합니다. 반면 malloc 된 버전에는 기본값이없고 인턴 참조는 초기화되지 않습니다.




항상 C ++에서 새로운 것을 사용하십시오. 유형이 지정되지 않은 메모리 블록이 필요한 경우 new 연산자를 직접 사용할 수 있습니다.

void *p = operator new(size);
   ...
operator delete(p);



새로운 / 삭제 대신에 malloc / free를 사용하는 경우는 realloc을 사용하여 C ++에서 realloc 할 수있는 기능이 없기 때문에 할당 및 재 할당 (간단한 포드 유형, 객체가 아님) 할 수 있습니다. (더 많은 C ++ 접근)




건설 / 파괴가 필요하지 않고 재 할당이 필요한 데이터로 작업하는 경우 (예 : int 배열이 큰 경우), malloc / free는 새로운 memcpy보다 빠른 realloc을 제공하므로 좋은 선택이라고 생각합니다 -delete (그것은 내 리눅스 박스에 있지만 플랫폼에 따라 다를 수 있음). POD가 아니고 작성 / 삭제가 필요한 C ++ 오브젝트로 작업하는 경우 new 및 delete 연산자를 사용해야합니다.

어쨌든, 나는 왜 당신이 당신의 malloced 메모리를 해제하고 새로운 것으로 할당 된 객체를 삭제한다면, 두가지를 사용해서는 안된다는 것을 알지 못한다. (큰 배열을 재배치한다면 속도가 향상 될 때도있다. POD의) realloc이 제공 할 수 있습니다.

당신이 그것을 필요로하지 않는 한, 당신은 C ++로 new / delete를 고수해야한다.




귀하의 질문에 대답하기 위해 mallocnew 의 차이점을 알아야 합니다 . 차이점은 간단합니다.

malloc 은 메모리를 할당 하고 new 는 메모리를 할당하고 메모리를 할당하는 객체 의 생성자호출합니다 .

따라서 C로 제한되지 않는 한, 특히 C ++ 객체를 다룰 때 malloc을 사용하지 않아야합니다. 그것은 당신의 프로그램을 깨뜨리는 방법이 될 것입니다.

또한 freedelete 의 차이는 완전히 동일합니다. 차이점은 delete 가 메모리를 해제하는 것 외에도 객체의 소멸자를 호출한다는 것입니다.




Links