무료는 얼마나 많은 것을 무료로 알 수 있습니까?


384

C 프로그래밍에서, 당신은 free에 대한 인수로 당신이 좋아하는 어떤 종류의 포인터라도 전달할 수 있습니다. 그것은 할당 된 메모리의 크기를 어떻게 알 수 있습니까? 일부 함수에 포인터를 전달할 때마다 크기도 전달해야합니다 (즉, 10 요소의 배열은 배열의 크기를 알기 위해 매개 변수로 10을 받아야합니다). 그러나 크기를 전달할 필요는 없습니다. 무료 기능. 왜 그렇지 않고 배열 길이의 여분의 변수를 카트로 묶을 필요가 없도록 자신의 함수 에서이 동일한 기술을 사용할 수 있습니까?


비슷한 질문 : stackoverflow.com/questions/851958/... (I이 상당히 중복되지 말하고 싶지만하지만)
존 카터

버디 시스템은 각각의 블록의 오버 헤드없이, 포인터에 기초하여 알아낼 수를 수행하는 또 다른 방법이다.
EvilTeach

이 게시물은 잘 설명합니다 : stackoverflow.com/questions/1957099/…
Zeeshan Mahmood

답변:


348

를 호출 할 때 malloc()할당 할 메모리 양을 지정합니다. 실제로 사용되는 메모리의 양은 이보다 약간 많으며 블록의 크기를 기록하는 추가 정보를 포함합니다. 다른 정보에 (안심하게) 액세스 할 수 없으며 –-)도 안됩니다.

를 호출 free()하면 추가 정보를보고 블록의 크기를 확인합니다.


44
참고로, 예를 들어 BSD는 ed 포인터 malloc_size()에서 블록 크기에 안정적으로 액세스해야합니다 malloc(). 그러나 신뢰할 수 있고 이식 가능한 방법은 없습니다.
laalto

50
이 추가 정보 블록이 반환 된 포인터 앞에 있다고 말하는 것이 중요하다고 생각합니다.
Georg Schölly

39
@gs 글쎄, 구현에 따라 다릅니다. 그러나 그렇습니다.
Falaina

31
free()프로그래머가 malloc()블록의 크기를 정확하게보고하도록 요구하는 경우 공포를 상상할 수 있습니까 ? 메모리 누수가 그대로 불량입니다.
MusiGenesis

35
왜이 정보를 malloc()및에 사용할 수 free()있지만 배열의 크기를 저장해야합니까? blockSize(ptr)어쨌든 정보를 저장하는 것과 같은 일을 할 수없는 이유는 무엇 입니까?
corsiKa

144

C 메모리 할당 함수의 대부분의 구현은 각 블록에 대한 계정 정보를 인라인 또는 개별적으로 저장합니다.

한 가지 일반적인 방법 (인라인)은 실제로 요청한 메모리와 헤더를 모두 최소 크기로 채우는 것입니다. 예를 들어, 20 바이트를 요청하면 시스템은 48 바이트 블록을 할당 할 수 있습니다.

  • 크기, 특수 마커, 체크섬, 다음 / 이전 블록에 대한 포인터 등을 포함하는 16 바이트 헤더.
  • 32 바이트 데이터 영역 (20 바이트는 16의 배수로 채워짐)

귀하에게 제공된 주소는 데이터 영역의 주소입니다. 그런 다음 블록 free을 비울 때 단순히 주소를 지정하고 해당 주소 나 주변 메모리를 채우지 않았다고 가정하면 회계 정보를 바로 확인하십시오. 그래픽으로 보면 다음과 같습니다.

 ____ The allocated block ____
/                             \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
          ^
          |
          +-- The address you are given

헤더와 패딩의 크기는 완전히 구현 정의되어 있습니다 (실제로 전체가 구현 정의 되어 있지만 (a) 인라인 회계 옵션이 일반적입니다).

계정 정보에 존재하는 체크섬 및 특수 마커는 종종 "메모리 아레나 손상"또는 "더블 프리"와 같이 오류를 덮어 쓰거나 두 번 해제하면 오류의 원인이됩니다.

패딩 (할당을보다 효율적으로 만들기 위해)은 때때로 문제를 일으키지 않고 요청 된 공간의 끝을 약간 넘어 쓸 수있는 이유입니다 (여전히 그렇게하지 마십시오. 정의되지 않은 동작이며 때로는 작동하기 때문에 작동하지 않습니다) t는 괜찮습니다).


(a)malloc 128 바이트 이하를 요청했다고 가정 할 때 (시스템에서 가장 큰 구조의 크기 인) 128 바이트를 갖는 임베디드 시스템에서 구현을 작성 했습니다 (더 많은 요청은 NULL 반환 값을 충족해야합니다. 128 바이트 청크의 할당 여부를 결정하기 위해 매우 간단한 비트 마스크 (즉, 인라인이 아닌)가 사용되었습니다.

내가 개발 한 다른 사람들은 16 바이트 청크, 64 바이트 청크, 256 바이트 청크 및 1K 청크에 대해 다른 풀을 사용했으며 비트 마스크를 사용하여 다시 사용하거나 사용 가능한 블록을 결정했습니다.

이 두 옵션은 회계 정보의 오버 헤드를 줄이고 속도 증가 관리 mallocfree우리가 작업하던 환경에서 특히 중요합니다 (해제 할 때 인접한 블록을 병합 할 필요).


@paxdiablo 이것이 malloc이 인접한 메모리 블록을 할당하지 않는다는 것을 의미합니까?
user10678

2
@ user10678의 유일한 실제 요구 사항은 malloc성공적인 경우 최소한 요청한 것보다 큰 메모리 블록을 제공한다는 것입니다. 개별 블록은 요소 내에서 요소에 액세스하는 방식과 관련하여 연속적이지만 블록의 출처가 연속적 일 필요는 없습니다.
paxdiablo

관련 질문 : 해제 할 때 크기를 지정하여 크기를 저장할 필요가없는 malloc / free의 변형이없는 이유는 무엇입니까?
user253751

@ user253751 은 포인터 자체에서 추적해야 할 사항이 하나 있기 때문 입니다. 그것은 불필요한 모두의 위험 : void *x = malloc(200); free(x, 500);되어 있지 아니라 :-) 어떤 경우, 효율성을 위해, 끝까지가는 실제 버퍼의 크기가 클 수 있습니다 (그냥 이것에 의존 할 수 있습니다).
paxdiablo

@paxdiablo 또한 크기를 유지하기 위해 메모리 낭비를 방지합니다.
user253751

47

로부터 comp.lang.c자주 묻는 질문 목록 : 어떻게 확보하기 위해 얼마나 많은 바이트를 무료로 알고는 무엇입니까?

malloc / free 구현은 할당 된 각 블록의 크기를 기억하므로 해제 할 때 크기를 상기시킬 필요가 없습니다. (일반적으로 크기는 할당 된 블록에 인접하게 저장되므로 할당 된 블록의 경계가 약간 초과 된 경우에도 일반적으로 문제가 발생합니다)


2
이것은 대답이 아닙니다. 문제는 정확히 이것입니다. 왜 자유로이 블록의 크기를 안정적으로 찾을 수는 있지만 프로그래머가 사용할 수있는 기능이 없습니까?
Bananach

이것은 실제로 malloc api의 구현 세부 사항이며 표준 정보로 내 정보를 다시 얻을 수있는 API는 없습니다. "시스템"은 그것을 기록하고 그것을 사용합니다 free. 어쩌면 대답이 당신을 만족시키지 못하지만 더 일반적으로 적용 가능한 정보가있는 것을 얻지 못할 것이라고 생각합니다 :-)
jdehaan

6

이 답변은 free ()가 할당 해제 할 메모리 양을 어떻게 알 수 있습니까? 에서 재배치되었습니다 . 나는 명백한 중복 질문으로 대답하지 못하게 막혔다. 이 답변은이 복제본과 관련이 있어야합니다.


의 경우 malloc, 힙 할당자는 free나중에 리턴 된 메모리에 필요한 관련 세부 사항에 대한 원래 리턴 포인터의 맵핑을 저장합니다 . 이것은 일반적으로 메모리 영역의 크기를 사용중인 할당 자와 관련된 모든 형태, 예를 들어 원시 크기, 또는 할당을 추적하는 데 사용되는 이진 트리의 노드 또는 사용중인 메모리 "단위"의 수로 저장합니다.

free포인터의 이름을 바꾸거나 어떤 식 으로든 복제해도 실패하지 않습니다. 그러나 참조 횟수는 계산되지 않으며 첫 번째 값만 free정확합니다. 추가 free는 "더블 프리"오류입니다.

free이전에 반환 된 값과 다른 값을 가진 포인터를 사용 하려고 시도 malloc했지만 아직 해제되지 않은 것은 오류입니다. 에서 반환 된 메모리 영역을 부분적으로 해제 할 수 없습니다 malloc.


malloc 호출에 의해 반환되는 포인터의 값을 변경했습니다. 그리고 나는 오류없이 그것을 풀었다. 왜? 여기를 참조하십시오 : stackoverflow.com/questions/42618390/…
smwikipedia

4

관련 참고 사항 GLib 라이브러리에는 암시 적 크기를 저장하지 않는 메모리 할당 기능이 있으며 size 매개 변수를 free로 전달하면됩니다. 이것은 오버 헤드의 일부를 제거 할 수 있습니다.


3

malloc()그리고 free()그것은 특정의 대답을하기 어렵다 있도록 시스템 / 컴파일러 의존한다.

이 다른 질문에 대한 자세한 정보 .


2
그것들은 실제로 라이브러리에 의존적입니다 (일반적으로 OS와 매우 밀접하게 연결된 C 라이브러리). 컴파일러에게는 함수일뿐입니다.
Donal Fellows

2

힙 관리자는 호출했을 때 어딘가에 할당 된 블록에 속하는 메모리 양을 저장했습니다 malloc.

나는 한 번도 직접 구현하지는 않았지만 할당 된 블록 바로 앞에있는 메모리에 메타 정보가 포함될 수 있습니다.


3
그것은 하나의 가능한 구현이지만, 모든 메모리가 완전히 다른 페이지의 단일 테이블에서 추적되는 시스템을 고안 할 수 있으며, 할당되는 메모리 풀과 가까운 곳은 아닙니다.
ephemient

2

원래 기술은 약간 큰 블록을 할당하고 처음에 크기를 저장 한 다음 응용 프로그램에 나머지 블로그를 제공하는 것이 었습니다. 여분의 공간은 크기를 유지하며 재사용을 위해 사용 가능한 블록을 함께 연결합니다.

그러나 캐시 및 메모리 관리 동작 불량과 같은 트릭에는 특정 문제가 있습니다. 블록에서 바로 메모리를 사용하면 불필요하게 페이지를 넘기는 경향이 있으며 공유 및 쓰기시 복사를 복잡하게하는 더티 페이지도 생성합니다.

따라서보다 고급 기술은 별도의 디렉토리를 유지하는 것입니다. 메모리 영역이 동일한 2의 거듭 제곱을 사용하는 이국적인 접근 방식도 개발되었습니다.

일반적으로 답은 상태를 유지하기 위해 별도의 데이터 구조가 할당됩니다.


1

질문의 후반부에 대답하려면 그렇습니다. 가능하며 C의 일반적인 패턴은 다음과 같습니다.

typedef struct {
    size_t numElements
    int elements[1]; /* but enough space malloced for numElements at runtime */
} IntArray_t;

#define SIZE 10
IntArray_t* myArray = malloc(sizeof(intArray_t) + SIZE * sizeof(int));
myArray->numElements = SIZE;

이것은 BSD malloc이 작은 오브젝트에 사용하는 것과는 완전히 다른 기술입니다 (Pascal 스타일 배열을 만드는 데는 완벽하게 좋은 기술 임)
Pete Kirkham

0

malloc을 호출하면 요구 사항에서 더 많은 바이트를 소비합니다. 이 더 많은 바이트 소비에는 체크섬, 크기 및 기타 추가 정보와 같은 정보가 포함됩니다. 우리가 그 시간에 무료로 전화하면 주소를 찾고 추가 블록이 얼마나 많은지 추가 정보로 직접 이동합니다.


0

두 번째 질문에 대답하기 위해, 예를 malloc() 들어 모든 배열 내부의 첫 번째 셀을 배열의 크기에 할당하는 것과 동일한 기술을 사용할 수 있습니다 . 추가 크기 인수를 보내지 않고 배열을 보낼 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.