Выделение памяти в си (более 4Гб)

  1. Объяснте, как (почему) это работает?

Естественно ни оперативки ни даже жёсткого диска такого размера у меня нет.

#include<stdlib.h>
#include <stdio.h>
int main()
{
  size_t d[500000000000 + 1];
    
  d[0] = 10;
  d[5000000] = 20;
  d[50000000] = 30;
  d[500000000] = 40;
  d[5000000000] = 50;
  d[50000000000] = 60;
  d[500000000000] = 70;

  printf("elements=%llu, size=%llu\n", sizeof(d)/sizeof(size_t), sizeof(d));
  printf("d[0]=%llu\n",               d[0]);
  printf("d[5.000.000]=%llu\n",       d[5000000]);
  printf("d[50.000.000]=%llu\n",      d[50000000]);
  printf("d[500.000.000]=%llu\n",     d[500000000]);
  printf("d[5.000.000.000]=%llu\n",   d[5000000000]);
  printf("d[50.000.000.000]=%llu\n",  d[50000000000]);
  printf("d[500.000.000.000]=%llu\n", d[500000000000]);
  
  return 0;
}

вывод:

elements=500000000001, size=4000000000008 
d[0]=10 
d[5.000.000]=20
d[50.000.000]=30 
d[500.000.000]=40 
d[5.000.000.000]=50
d[50.000.000.000]=60 
d[500.000.000.000]=70

собираю так: (x64)

gcc.exe -m64 test.c -O3 -o test.exe
  1. Можно ли выделить блок памяти более 4Гб (в 64 битном приложении)?

Как это правильно работает в си? (malloc больше не может, как я понял)


Ответы (1 шт):

Автор решения: Кирилл Малышев

У вас стоит опция -O3. Компилятор понимает, что массив на самом деле тут не нужен и производит оптимизацию, просто подставляя в вывод константы.

.LC0:
        .string "elements=%llu, size=%llu\n"
.LC1:
        .string "d[0]=%llu\n"
.LC2:
        .string "d[5.000.000]=%llu\n"
.LC3:
        .string "d[50.000.000]=%llu\n"
.LC4:
        .string "d[500.000.000]=%llu\n"
.LC5:
        .string "d[5.000.000.000]=%llu\n"
.LC6:
        .string "d[50.000.000.000]=%llu\n"
.LC7:
        .string "d[500.000.000.000]=%llu\n"
main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        movabs  rdx, 4000000000008
        movabs  rsi, 500000000001
        call    printf
        mov     esi, 10
        mov     edi, OFFSET FLAT:.LC1
        xor     eax, eax
        call    printf
        mov     esi, 20
        mov     edi, OFFSET FLAT:.LC2
        xor     eax, eax
        call    printf
        mov     esi, 30
        mov     edi, OFFSET FLAT:.LC3
        xor     eax, eax
        call    printf
        mov     esi, 40
        mov     edi, OFFSET FLAT:.LC4
        xor     eax, eax
        call    printf
        mov     esi, 50
        mov     edi, OFFSET FLAT:.LC5
        xor     eax, eax
        call    printf
        mov     esi, 60
        mov     edi, OFFSET FLAT:.LC6
        xor     eax, eax
        call    printf
        mov     esi, 70
        mov     edi, OFFSET FLAT:.LC7
        xor     eax, eax
        call    printf
        xor     eax, eax
        add     rsp, 8
        ret

https://godbolt.org/z/oh3c8T

Без этой опции память будет выделяться. Скорее всего, при выполнении такого кода программа аварийно завершится.

https://godbolt.org/z/8a9baM

→ Ссылка