동적 메모리 할당은 널리 사용되는 구현에서 C와 C ++에서 다릅니 까?
각 언어 표준이 진행되는 한 C는 malloc()
제품군을 통해서만 동적 메모리 할당을 제공 하는 반면 C ++에서는 가장 일반적인 할당 형식이 ::operator new()
. C 스타일 malloc은 C ++에서도 사용할 수 있으며, 많은 "아기의 첫 번째 할당 자"예제에서이를 핵심 할당 함수로 사용하지만 현대 컴파일러가 실제 생산 연산자를 어떻게 구현하는지 궁금합니다.
그것은 단지 얇은 래퍼입니까 malloc()
, 아니면 일반적인 C 프로그램과 비교하여 일반적인 C ++ 프로그램의 메모리 할당 동작이 다소 다르기 때문에 근본적으로 다르게 구현됩니까?
[ 편집 : 주요 차이점은 일반적으로 다음과 같이 설명됩니다. AC 프로그램은 더 적고 더 크고 수명이 긴 할당을 가지고있는 반면 C ++ 프로그램은 많은, 작고, 짧은 할당을 가지고 있습니다. 그것이 틀렸다면 부담없이 들으십시오. 그러나 이것을 고려하면 도움이 될 것 같습니다.]
GCC와 같은 컴파일러의 경우 단일 코어 할당 구현을 하나만 가지고 모든 관련 언어에 사용하는 것이 쉬울 것이므로 각 언어에서 결과 할당 성능을 최적화하려는 세부 사항에 차이가 있는지 궁금합니다.
업데이트 : 모든 훌륭한 답변에 감사드립니다! GCC에서 이것은 ptmalloc 에 의해 완전히 해결되고 MSVC도 malloc
코어에서 사용하는 것처럼 보입니다 . MSVC-malloc이 어떻게 구현되는지 아는 사람이 있습니까?
다음은에서 사용하는 구현입니다 g++ 4.6.1
.
_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) throw (std::bad_alloc)
{
void *p;
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
p = (void *) malloc (sz);
while (p == 0)
{
new_handler handler = __new_handler;
if (! handler)
#ifdef __EXCEPTIONS
throw bad_alloc();
#else
std::abort();
#endif
handler ();
p = (void *) malloc (sz);
}
return p;
}
이것은 libstdc++-v3/libsupc++/new_op.cc
g ++ 소스 배포판 내부에서 찾을 수 있습니다.
보시다시피, 그것은 주위에 상당히 얇은 래퍼 malloc
입니다.
편집 많은 시스템 malloc
에서 일반적으로 mallopt
환경 변수를 호출 하거나 설정 하여의 동작을 미세 조정할 수 있습니다 . 다음은 Linux에서 사용할 수있는 일부 기능에 대해 설명하는 기사 입니다.
위키 백과에 따르면 , glibc
버전이라는 할당의 수정 된 버전 사용 2.3 ptmalloc
자체의 파생, dlmalloc
에 의해 설계된 더그 레아를 . 흥미롭게도 Doug Lea 에 대한 기사dlmalloc
에서 다음과 같은 관점을 제공합니다 (강조).
동적 메모리 할당에 거의 독점적으로 의존하는 일부 C ++ 프로그램을 작성한 후 할당 자의 첫 번째 버전을 작성했습니다. 나는 그들이 내가 예상했던 것보다 훨씬 더 느리게 그리고 / 또는 훨씬 더 많은 총 메모리 소비로 실행된다는 것을 발견했습니다. 이것은 내가 실행중인 시스템 (주로 SunO 및 BSD의 당시 현재 버전)의 메모리 할당 자의 특성 때문이었습니다. 이에 대응하기 위해 처음에는 다양한 클래스에 대해 new operator를 오버로딩하여 C ++로 여러 특수 목적 할당자를 작성했습니다. 이들 중 일부는 1989 년 C ++ 보고서 기사 컨테이너 클래스에 대한 일부 스토리지 할당 기술에 채택 된 C ++ 할당 기술에 대한 문서에 설명되어 있습니다.
그러나 나는 그 당시에 작성하고 있던 종류의 범용 프로그래밍 지원 클래스를 빌드 할 때 동적으로 할당되고 많이 사용되는 경향이있는 각각의 새 클래스에 대한 특수 할당자를 빌드하는 것이 좋은 전략이 아니라는 것을 곧 깨달았습니다. (1986 년부터 1991 년까지 저는 GNU C ++ 라이브러리 인 libg ++의 주 저자였습니다.) 프로그래머가 유혹에 빠지지 않도록 정상적인 C ++ 및 C로드에서 충분히 좋은 할당자를 작성 하려면 더 광범위한 솔루션이 필요 했습니다. 매우 특수한 조건을 제외하고 특수 목적 할당자를 작성하십시오.
이 기사에서는이 할당 자에 대한 몇 가지 주요 설계 목표, 알고리즘 및 구현 고려 사항에 대한 설명을 제공합니다.
대부분의 구현에서 operator new()
바로 호출합니다 malloc()
. 사실 표준조차도 그것을 기본 전략으로 제안합니다 . 물론 operator new
더 나은 성능을 원하면 일반적으로 클래스에 대해 자체를 구현할 수 있지만 기본값은 일반적으로 malloc()
.
glibc new operator는 malloc을 둘러싼 얇은 래퍼입니다. 그리고 glibc malloc은 다양한 크기 할당 요청에 대해 다른 전략을 사용합니다. 구현 또는 적어도 여기 에서 의견을 볼 수 있습니다 .
다음은 malloc.c의 주석에서 발췌 한 것입니다.
/*
47 This is not the fastest, most space-conserving, most portable, or
48 most tunable malloc ever written. However it is among the fastest
49 while also being among the most space-conserving, portable and tunable.
50 Consistent balance across these factors results in a good general-purpose
51 allocator for malloc-intensive programs.
52
53 The main properties of the algorithms are:
54 * For large (>= 512 bytes) requests, it is a pure best-fit allocator,
55 with ties normally decided via FIFO (i.e. least recently used).
56 * For small (<= 64 bytes by default) requests, it is a caching
57 allocator, that maintains pools of quickly recycled chunks.
58 * In between, and for combinations of large and small requests, it does
59 the best it can trying to meet both goals at once.
60 * For very large requests (>= 128KB by default), it relies on system
61 memory mapping facilities, if supported.
*/
Visual C ++에서 new
식에 들어가면 다음 코드가 표시됩니다 new.cpp
.
#include <cstdlib>
#include <new>
_C_LIB_DECL
int __cdecl _callnewh(size_t size) _THROW1(_STD bad_alloc);
_END_C_LIB_DECL
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{ // try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
따라서 VC ++ new
도 malloc()
호출을 래핑합니다 .
성능의 문제가 아닙니다. 다음 pA = new A
과 다른 부작용이 있습니다.pA = (A*)malloc(sizeof(A));
In the second one, the A's constructor is not called. To come to a same effect you should do
pA = (A*)malloc(sizeof(A));
new(pA)A();
where new is the "placement new"...
void* operator new(size_t sz, void* place)
{ return place; }
ReferenceURL : https://stackoverflow.com/questions/7443782/does-dynamic-memory-allocation-differ-in-c-and-c-in-popular-implementations
'development' 카테고리의 다른 글
time ()은 좋은 소금입니까? (0) | 2020.12.30 |
---|---|
MVVM 모델에서 모델은 INotifyPropertyChanged 인터페이스를 구현해야합니까? (0) | 2020.12.30 |
데이터베이스 연결 문자열에 최대 풀 크기를 설정해야합니까? (0) | 2020.12.30 |
Node.js에서 process.nextTick의 적절한 사용 사례는 무엇입니까? (0) | 2020.12.30 |
C에서 NULL은 항상 0입니까? (0) | 2020.12.30 |