Total Articles 494
VLA(배열의 길이가 compile time에 결정되지 않고 runtime에 결정이 되는)의 경우 해당 배열은 stack에서 확보가 되는지, 아니면 heap에서 확보가 되는지를 테스트해 보았습니다.
[code]
#include <stdlib.h>#include <stdio.h>void debug(const char* msg, void* p) {printf("%s=%p\n", msg, p);}void test() {char stack = 1;debug("stack", &stack); // stack 영역이 대충 어디인지 알아 본다.char* heap = (char*)malloc(256);debug("heap", heap); // heap 영역이 대충 어디인지 알아 본다.free(heap);}size_t len1;size_t len2;size_t len3;int main() {test();scanf("%zu", &len1);char arr1[len1]; // 가변 길이 배열.debug("arr1", arr1);scanf("%zu", &len2);char arr2[len2]; // 가변 길이 배열.debug("arr2", arr2);scanf("%zu", &len3);char arr3[len3]; // 가변 길이 배열.debug("arr3", arr3);printf("%zu\n", arr1 - arr2);printf("%zu\n", arr2 - arr3);return 0;}
[result]
입력(각각의 배열의 크기)은 256, 256, 256으로 하였습니다.
stack=0x7fffcb1adddf // stack 영역은 대충 0x7fff... 로 시작하는구나.
heap=0x558d4d96d280 // heap 영역은 대충 0x55... 로 시작하는구나.
256 256 256 // 입력값.
arr1=0x7fffcb1adcf0 // VLA는 stack 영역에 잡힘.
arr2=0x7fffcb1adbf0 // VLA는 stack 영역에 잡힘.
arr3=0x7fffcb1adaf0 // VLA는 stack 영역에 잡힘.
256 // 포인터의 차이는 배열의 크기만큼임.
256 // 포인터의 차이는 배열의 크기만큼임.
[disassemble]
실제로 disassemble된 코드는 다음과 같습니다(필요한 배열의 크기를 16의 배수로 만들어 그만큼 stack 영역을 확보함).
char arr1[len1];
add $0xf,%raxand $0xfffffffffffffff0,%rax
sub %rax,%rsp
[테스트 환경]
OS : Linux home 4.16.0-kali2-amd64 #1 SMP Debian 4.16.12-1kali1 (2018-05-28) x86_64 GNU/LinuxCompiler : gcc (Debian 7.3.0-23) 7.3.0Build command : gcc -O2 -g -Wall -o vla_test vla_test.c
ps : 위키( https://en.wikipedia.org/wiki/Variable-length_array )에 다음과 같은 문구가 있으니 참고하시기 바랍니다(VLA는 받드시 stack에서 확보해야 한다는 보장은 없다. 즉 컴파일러 마음대로이다).
- The GNU C Compiler allocates memory for VLAs with automatic storage duration on the stack. VLAs, like all objects in C, are limited to SIZE_MAX bytes.
- VLAs can also be allocated on the heap and accessed using a pointer to VLA.