programing

말로크는 C에서 얼마나 클 수 있습니까?

lovejava 2023. 9. 21. 19:59

말로크는 C에서 얼마나 클 수 있습니까?

C에 26901^2*사이즈(더블)의 malloc이 있습니다.

여기서 가장 큰 가치가 무엇인지 생각하게 만들었죠.

또한 이 2D 배열에 액세스하기 위해 매크로를 정의하는 데 문제가 없습니까?

 #define DN(i,j) ((int)i * ny + (int)j)

왜냐하면 이것은 저에게 효과가 없는 것 같기 때문입니다. 아니면 최소한 확실하지 않습니다.A[DN(indx,jndx)]이 실제로 보고 있는 것을 알려주기 위해 매크로에서 전체 보기를 다이브하는 방법을 알 수 없습니다.

관측치

one glibc가 사용하는 것과 같은 일반적인 할당자를 가정하면 다음과 같은 몇 가지 관측 결과가 있습니다.

  1. 메모리가 실제로 사용되는지 여부에 관계없이 해당 영역은 가상 메모리에 연속적으로 예약되어야 합니다.
  2. 가장 큰 자유 연속 영역은 기존 메모리 영역의 메모리 사용량과 해당 영역의 가용성에 따라 달라집니다.
  3. 매핑 방법은 아키텍처와 OS에 따라 달라집니다. 영역을 기본적인 이러한 방식예)에 영향을 받습니다예:malloc페이지를 획득하기 위해 를 통해 호출합니다.

실험.

여기에 가능한 최대 블록을 할당하는 간단한 프로그램이 있습니다.gcc largest_malloc_size.c -Wall -O2:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static void *malloc_wrap(size_t size)
{
    void *p = malloc(size);
    if (p) {
        printf("Allocated %zu bytes from %p to %p\n", size, p, p + size);
    }
    else {
        printf("Failed to allocated %zu bytes\n", size);
    }
    return p;
}

int main()
{
    size_t step = 0x1000000;
    size_t size = step;
    size_t best = 0;
    while (step > 0)
    {
        void *p = malloc_wrap(size);
        if (p) {
            free(p);
            best = size;
        }
        else {
            step /= 0x10;
        }
        size += step;
    }
    void *p = malloc_wrap(best);
    if (p) {
        pause();
        return 0;
    }
    else {
        return 1;
    }
}

(()./a.out내 )에Linux stanley 2.6.32-24-generic-pae #39-Ubuntu SMP Wed Jul 28 07:39:26 UTC 2010 i686 GNU/Linux기계는 다음 결과를 얻습니다.

<snip>
Allocated 2919235584 bytes from 0x9763008 to 0xb7763008
Allocated 2936012800 bytes from 0x8763008 to 0xb7763008
Failed to allocated 2952790016 bytes
Failed to allocated 2953838592 bytes
Failed to allocated 2953904128 bytes
Failed to allocated 2953908224 bytes
Allocated 2936012800 bytes from 0x85ff008 to 0xb75ff008

이것은 정확히 2800MiB의 할당입니다.다음에서 관련 매핑 관찰:

<snip>
0804a000-0804b000 rw-p 00001000 08:07 3413394    /home/matt/anacrolix/public/stackoverflow/a.out
085ff000-b7600000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0 
b7621000-b7700000 ---p 00000000 00:00 0 
b7764000-b7765000 rw-p 00000000 00:00 0 
b7765000-b78b8000 r-xp 00000000 08:08 916041     /lib/tls/i686/cmov/libc-2.11.1.so
<snip>
bfc07000-bfc1c000 rw-p 00000000 00:00 0          [stack]

결론

힙이 프로그램 데이터와 코드 사이의 영역에서 확장된 것으로 보이며 공유 라이브러리 매핑은 사용자/커널 메모리 공간 경계(이 시스템에서는 3G/1G임이 분명합니다)와 잘 맞춥니다.

이 결과는 malloc을 사용하여 할당할 수 있는 최대 공간이 대략 다음과 같음을 나타냅니다.

  1. 사용자 공간 영역(예: 3GB)
  2. 힙 시작까지의 오프셋 감소(프로그램 코드 및 데이터)
  3. 기본 스레드 스택에 예약된 공간 감소
  4. 공유 라이브러리의 매핑된 모든 공간이 차지하는 공간 감소
  5. 마지막으로 힙에서 사용 가능한 영역 내에서 기본 시스템 호출로 찾을 수 있는 가장 큰 연속 영역(다른 매핑에 의해 단편화될 수 있음)

메모들

glibc 및 리눅스 구현과 관련하여 다음과 같은 수동 스니펫이 매우 중요합니다.

malloc

   Normally, malloc() allocates memory from the heap, and adjusts the size
   of the heap as required, using sbrk(2).  When allocating blocks of mem‐
   ory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation
   allocates the memory as a  private  anonymous  mapping  using  mmap(2).
   MMAP_THRESHOLD  is  128  kB  by  default,  but is adjustable using mal‐
   lopt(3).

mmap

   MAP_ANONYMOUS
          The mapping is not backed by any file; its contents are initial‐
          ized to zero.

뒷말

이 테스트는 x86 커널에서 수행되었습니다.저는 x86_64 커널에서 비슷한 결과를 얻을 것으로 기대합니다. 비록 엄청나게 큰 메모리 영역이 반환되었지만 말입니다.다른 다의 수 .malloc 다를 수 .

그것은 당신의 malloc 구현에 달려있습니다!

위키피디아에 따르면, "v2.3 릴리스 이후 GNU C 라이브러리(glibc)는 수정된 ptmalloc2를 사용하며, 그 자체는 dlmalloc v2.7.0을 기반으로 합니다." dlmalloc은 더그 레아(Doug Lea)의 malloc 구현을 나타냅니다.이 구현에서 주목해야 할 중요한 점은 운영 체제의 메모리 매핑 파일 기능을 통해 큰 mallocs가 구현되므로 이러한 블록은 연속되는 블록을 찾는 많은 문제 없이 실제로 상당히 클 수 있습니다.

malloc 질문에 응답하므로(지정하지 않은 OS에 따라 다름) 다음을 정의합니다.

#define DN(i,j) ((int)i * ny + (int)j)

를 할도 있기 누군가가 할 수도 있기 때문입니다.DN(a+b,c)되는

((int)a+b * ny + (int)c)

아마도 당신이 원했던 것은 아닐 겁니다.그래서 괄호를 많이 쳐주세요.

#define DN(i,j) ((int)(i) * ny + (int)(j))

DN(indx,jndx)킴,printf("%d\n",DN(indx,jndx));

malloc로 호출하는 크기 매개변수는 size_t형으로 구현에 따라 다릅니다.자세한 내용은 이 질문을 참조하십시오.

여기서 가장 큰 가치가 무엇인지 생각하게 만들었죠.

26'901^2 = 723'663'801.두 배가 8바이트이면 8GB 미만입니다.메모리를 그만큼 많이 할당하는 데 전혀 문제가 없다고 생각하며 애플리케이션에서 (64비트 시스템에서) 일상적으로 훨씬 더 많이 할당합니다. (지금까지 본 메모리 사용량 중 가장 많은 것은 420GB(640GB RAM을 사용하는 Solaris 10 numa 시스템에서)였으며 연속 블록은 최대 24GB였습니다.)

가장 큰 값은 플랫폼에 의존하기 때문에 식별이 어렵습니다. 32비트 시스템과 유사하게 사용자 공간/커널 공간 분할에 의존합니다.현재 상황으로는, libc가 할당할 수 있는 한계에 도달하기 전에 먼저 실제 물리적 RAM의 한계에 도달할 것이라고 생각합니다.(커널은 신경쓰지 않습니다. 가상 메모리를 고정할 충분한 RAM이 있는지 여부도 고려하지 않고 가상 메모리를 확장하는 경우가 많습니다.)

질문할 수 있는 가장 큰 메모리 블록 malloc()는 가장 큰다입니다.size_tvalue - 이것은SIZE_MAX부터<limits.h>. 성공적으로 요청할 수 있는 최대 금액은 운영 체제와 개별 기계의 구성에 따라 달라집니다.

매크로가 안전하지 않습니다.다음과 같이 인덱스 계산을 수행합니다.int변수는 최대 32767의 범위만 가지면 됩니다.이 값보다 높으면 서명된 오버플로가 발생하여 정의되지 않은 동작이 발생할 수 있습니다.당신은 아마도 계산을 하는 것이 최선일 것입니다.size_t, 해당 유형은 유효한 배열 인덱스를 보유할 수 있어야 합니다.

#define DN(i, j) ((size_t)(i) * ny + (size_t)(j))

(그러나 만약 당신이 음의 값을 제공한다면i아니면j, 범위를 훨씬 벗어난 지수를 얻을 수 있습니다.)

언급URL : https://stackoverflow.com/questions/3463207/how-big-can-a-malloc-be-in-c