malloc이 요청한 것과 다른 바이트 수를 할당하는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/430163

  •  08-07-2019
  •  | 
  •  

문제

이 코드 조각이 있습니다

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main(){
    void *a, *b;

    a = malloc(16);
    b = malloc(16);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);

    a = malloc(1024);
    b = malloc(1024);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);  
}

마지막으로 할당된 블록 크기(16 또는 1024)를 인쇄하면 안 되나요?대신 24와 1032를 인쇄하므로 할당된 메모리 양에 8바이트가 추가된 것으로 보입니다.

내 문제는 (이 테스트 사례를 만들기 전에) 내가하는 것입니다 malloc() 함수(1024바이트)에서 할당된 결과를 반환합니다.함수 반환에서 블록 크기를 확인할 때 516개의 블록이 표시됩니다.왜 그런지 이해가 안 돼요.이것이 할당된 버퍼에서 일부 처리를 수행한 후 발생하는 메모리 손상의 원인일 수 있다고 생각합니다. :)

편집하다: 나는 본 적이 C의 포인터에서 배열의 크기를 어떻게 얻을 수 있습니까? 같은 질문을 하시는 것 같은데, 다시 게시해서 죄송합니다.

내 예제를 좀 더 구체적인 코드로 다시 작성했습니다.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

short int * mallocStuff(long int number, short int base){
    short int *array;
    int size=1024;

    array=(short int*)calloc(1,size);
    //array=(short int*)malloc(size);

    return array;
}

int main(){
    short int **translatedArray;

    translatedArray=malloc(4*sizeof(short int));

    int i;
    for(i=0;i<4;i++){
        translatedArray[i]=mallocStuff(0,0);

        if(i>0)
            printf("\n   block size (for a): %p-%p : %i",
                translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
    }

    return 0;
}

그리고 출력은

   block size (for a): 0x804a420-0x804a018 : 516
   block size (for a): 0x804a828-0x804a420 : 516
   block size (for a): 0x804ac30-0x804a828 : 516

위 게시물에 따르면 1024보다 큽니다.내가 잘못?

도움이 되었습니까?

해결책

버그가 있습니다.대신에:

translatedArray=malloc(4*sizeof(short int));

당신은 가지고 있어야

translatedArray=malloc(4*sizeof(short int*));

코드에서 누락된 포인터를 확인하세요.나는 이것이 당신이 관찰한 행동에서 비롯된 것이라고 생각합니다.


또한 0x804a420 - 0x804a018 = 1032, 아니다 516.공식 translatedArray[i] - translatedArray[i - 1] 당신에게 수를 제공합니다 강요 (짧은 정수 또는 더 간단하게는 shorts)의 수가 아니라 두 주소 사이에 있습니다. 바이트.

다른 팁

첫째, Malloc은 두 번의 연속적인 malloc 호출이 연속적인 포인터를 반환한다는 보장을 하지 않습니다.

둘째, 특정 아키텍처에 따라 다양한 정렬 규칙이 적용됩니다.때로는 단일 바이트를 요청할 수도 있지만 아키텍처에서는 8바이트 또는 4바이트 간격으로 할당하는 것을 선호합니다.

셋째, malloc은 할당된 블록의 크기 등을 저장하기 위해 약간의 오버헤드가 필요합니다.

문서에 명시된 내용 외에 malloc이 수행하는 작업에 대해 가정하지 마세요!

그만큼 malloc 함수는 일부 장부 정보를 저장하기 위해 항상 요청한 것보다 약간 더 많은 것을 할당합니다.결국 전화하면 free() 블록이 얼마나 큰지 알아야 합니다.

또한 일반적으로 malloc 구현에서는 요청된 크기를 8이나 16의 다음 배수 또는 다른 반올림 숫자로 반올림합니다.

업데이트:귀하의 질문에 대한 실제 대답은 귀하의 사용에 있습니다. short int 유형.형식화된 포인터 간에 포인터 산술(뺄셈)을 수행할 때 C와 C++는 다음과 같은 차이를 반환합니다. 숫자 지적한 것들.당신이 가리키고 있으니 short int, 크기가 2바이트인 경우 반환된 값은 예상한 값의 절반입니다.

반면에, malloc 항상 주어진 수의 할당 바이트, 나중에 결과를 무엇으로 캐스팅하든 상관 없습니다.이 시도:

    array=(short int*)malloc(sizeof(short int) * size);

두 개의 malloc 호출이 정확히 함께 묶인 블록을 반환한다는 보장은 없습니다. 실제로 결과에 대한 보장은 전혀 없습니다. 단, NULL이 아닌 경우 요청한 블록만큼 큰 블록을 가리킬 것이라는 점만 제외하면 됩니다.

내부적으로 대부분의 malloc은 힙 관리에 도움이 되는 작업 데이터를 보유합니다.예를 들어, 해당 8바이트에는 두 개의 포인터가 포함될 수 있습니다. 하나는 다음 블록을 가리키고 다른 하나는 이전 블록을 가리킵니다.어떤 OS를 실행하고 있는지 언급하지 않았기 때문에 그 8바이트가 무엇인지는 모르지만, malloc이 뒤에서 자체적으로 일부 메모리를 사용하는 것은 완전히 정상입니다.

일부 할당자(예: Windows)는 포인터가 주어진 블록 크기를 검색하는 라이브러리 기능을 제공하지만 일부는 다소 난해한 기능이므로 그렇지 않습니다.

malloc이 반환하는 내용은 malloc 구현과 아키텍처에 따라 다릅니다.다른 사람들이 이미 말했듯이 요청된 메모리 양 또는 NULL을 최소한으로 확보하는 것이 보장됩니다.이것이 때때로 배열의 끝을 지나서 쓸 수 있고 분할 오류가 발생하지 않는 이유이기도 합니다.그것은 당신이 실제로 이 메모리에 대한 유효한 접근 권한을 갖고 있기 때문입니다. 그러나 당신은 그것을 몰랐을 뿐입니다.

malloc()은 일반적으로 사용 가능한 힙을 다양한 크기의 청크로 분할하여 구현됩니다.귀하의 경우, malloc()은 2개의 연속적인 1024(또는 16) 바이트 청크를 반환합니다.언급한 8바이트 공간은 장부 정보를 위해 malloc()에서 사용됩니다.

뒤에서 무슨 일이 일어나고 있는지 이해하려면 여기에서 Doug Lea의 malloc() impl 노트를 참조하세요. http://g.oswego.edu/dl/html/malloc.html

malloc() 자체 오버헤드가 발생합니다.

두 개의 연속 할당이 처음부터 서로 옆에 있을 것이라는 보장은 없다는 것은 말할 것도 없습니다.

만약에 malloc null 이외의 것을 반환한 다음 할당된 메모리를 반환합니다. 귀하의 프로그램을 위해 당신이 전달한 크기가 있습니다 malloc.두 차이 호출의 반환 값 간의 포인터 차이를 다음으로 가져옵니다. malloc 어떤 값이든 가질 수 있으며 첫 번째 할당된 블록의 블록 크기와는 아무 관련이 없습니다(거의 없음).

이걸 찾았습니다.. 자세한 내용은 아래 링크를 확인하세요.

배당

먼저 다음 방정식을 사용하여 요청된 바이트를 버킷 배열의 인덱스로 변환하여 여유 풀에서 블록을 할당합니다.

필요 = 요청 + 8

필요한 경우 <= 16, 버킷 = 0

필요한 경우> 16, Bucket = (로그 (필요)/log (2)가 가장 가까운 정수로 반올림) -3

버킷에 의해 고정된 목록의 각 블록 크기는 블록 크기 = 2 버킷 + 4입니다.버킷의 목록이 null이면 목록에 블록을 추가하기 위해 sbrk 서브루틴을 사용하여 메모리가 할당됩니다.블록 크기가 페이지보다 작으면 sbrk 서브루틴을 사용하여 페이지를 할당하고, 블록 크기를 페이지 크기로 나누어 도달한 블록 수를 목록에 추가합니다.블록 크기가 페이지보다 크거나 같으면 sbrk 서브루틴을 사용하여 필요한 메모리가 할당되고 단일 블록이 버킷의 여유 목록에 추가됩니다.사용 가능한 목록이 비어 있지 않으면 목록의 선두에 있는 블록이 호출자에게 반환됩니다.그러면 목록의 다음 블록이 새 헤드가 됩니다.

http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm

포인터가 32/64비트 정수인 다음 배열의 크기를 나타내기 전에(부호 있는지 부호 없는지 알 수 없음)

그러면 할당된 메모리 양에 8바이트가 추가된 것 같습니다. malloc() 시스템의 구현은 힙 섹션이 얼마나 큰지, 시작 주소가 무엇인지 등과 같은 메타데이터 정보를 유지하기 위해 추가 바이트를 할당하는 것 같습니다.

플랫폼에 따라 다르지만.내 X86 시스템에서는 malloc() 최소 할당 중 17 바이트, 내가 요청하더라도 malloc(0).

int main(void) {
    int *p = malloc(0);
    if(p == NULL) {
        /* error handling */
    }
    printf("%d\n",p[-1]);/ *it prints 17 bytes */
    /* some code */
    return 0;
}

malloc()은 연속적인 메모리를 할당할 수 있지만, malloc()을 2번 호출하면 두 포인터 변수를 빼서 할당된 메모리가 연속적이기를 기대할 수 없습니다.

그러나 할당된 메모리는 커널 구현, 구체적으로 메모리 관리(VFS)의 일부인 가상 메모리입니다.애플리케이션 기능에는 영향을 미치지 않을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top