컴파일 시 할당된 메모리'는 무엇을 의미합니까?
C나 C++와 같은 프로그래밍 언어에서는 정적 메모리 할당과 동적 메모리 할당이 자주 사용됩니다.개념은 이해하지만 "모든 메모리가 컴파일 시간 동안 할당(예약)"이라는 문구는 항상 헷갈립니다.
컴파일은 높은 수준의 C/C++ 코드를 기계어로 변환하여 실행 파일을 출력하는 것으로 알고 있습니다.컴파일된 파일에서 메모리를 "할당"하려면 어떻게 해야 합니까?메모리는 항상 모든 가상 메모리 관리 기능과 함께 RAM에 할당되지 않습니까?
메모리 할당은 정의상 실행 시 개념 아닌가요?
C/C++ 코드에 1KB의 정적으로 할당된 변수를 만들면 실행 파일의 크기가 같은 양만큼 증가합니까?
이 페이지는 "Static allocation"이라는 제목 아래 구문이 사용되는 페이지 중 하나입니다.
컴파일 시에 할당된 메모리는 컴파일러가 컴파일 시에 해결되며 프로세스 메모리 맵 내에서 특정 항목이 할당됩니다.
예를 들어, 글로벌 어레이에 대해 생각해 보겠습니다.
int array[100];
컴파일러는 컴파일 시 어레이의 크기 및 데이터 저장소의 크기를 알고 있습니다.int
따라서 컴파일 시 어레이의 전체 크기를 알 수 있습니다.또한 글로벌 변수에는 디폴트로 스태틱스토리지 기간이 있습니다.프로세스 메모리 공간(.data/.bss 섹션)의 스태틱메모리 영역에 할당됩니다.이 정보를 바탕으로 컴파일러는 컴파일 중에 어레이가 그 정적 메모리 영역의 어떤 주소가 될지를 결정합니다.
물론 메모리 주소는 가상 주소입니다.프로그램에서는, 독자적인 메모리 영역 전체가 있는 것을 전제로 하고 있습니다(0x00000000 ~0xFFFFFF 등).따라서 컴파일러는 "OK, 어레이는 주소 0x00A33211에 있습니다"와 같은 가정을 할 수 있습니다.실행 시 해당 주소는 MMU 및 OS에 의해 실제/하드웨어 주소로 변환됩니다.
초기화된 정적 스토리지와 같은 값은 조금 다릅니다.예를 들어 다음과 같습니다.
int array[] = { 1 , 2 , 3 , 4 };
첫 번째 예에서는 컴파일러가 어레이를 할당하는 위치만 결정하고 실행 파일에 해당 정보를 저장합니다.
값이 초기화된 경우 컴파일러는 어레이의 초기값을 실행파일에 주입하고 프로그램 시작 시 어레이 할당 후 어레이에 이러한 값을 채워야 함을 프로그램 로더에 알리는 코드를 추가합니다.
다음은 컴파일러에 의해 생성된 어셈블리의 두 가지 예입니다(x86 타깃이 있는 GCC4.8.1).
C++ 코드:
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
출력 어셈블리:
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
보시는 바와 같이 값은 어셈블리에 직접 주입됩니다.어레이 내a
컴파일러는 16바이트의 제로 초기화를 생성합니다.표준에서는 스태틱하게 저장된 것은 디폴트로0으로 초기화되어야 한다고 되어 있기 때문입니다.
8.5.9(이니셜라이저) [주]:
정적 저장 기간의 모든 개체는 다른 초기화가 발생하기 전에 프로그램 시작 시 0으로 초기화됩니다.경우에 따라서는 나중에 추가 초기화가 이루어집니다.
컴파일러가 C++ 코드로 실제로 무엇을 하는지 보기 위해 코드를 분해할 것을 항상 권장합니다.이는 스토리지 클래스/기간(이 질문처럼)부터 고급 컴파일러 최적화까지 적용됩니다.컴파일러에게 어셈블리를 생성하도록 지시할 수 있지만, 인터넷에는 이 작업을 편리하게 수행할 수 있는 훌륭한 도구가 있습니다.제가 가장 좋아하는 것은 GCC 익스플로러입니다.
컴파일시에 메모리를 할당하면, 실행시에 추가의 할당이 없어집니다.콜은 없습니다.malloc
,new
또는 기타 동적 할당 방식입니다.모든 메모리가 항상 필요한 것은 아니더라도 메모리 사용량은 일정합니다.
메모리 할당은 기본적으로 런타임 개념 아닌가요?
메모리는 실행 시간 전에는 사용되지 않지만 실행 시작 직전에 할당이 시스템에 의해 처리됩니다.
C/C++ 코드에 1KB의 정적으로 할당된 변수를 만들면 실행 파일의 크기가 같은 양만큼 커집니까?
static을 선언하는 것만으로 실행 파일의 크기가 몇 바이트 이상 증가하지는 않습니다.0이 아닌 초기값으로 선언하면 (초기값을 유지하기 위해) 이 값이 선언됩니다.링커는 이 1KB를 시스템 로더가 실행 직전에 작성하는 메모리 요건에 추가합니다.
컴파일 시에 할당된 메모리는 프로그램을 로드하면 메모리의 일부가 즉시 할당되고 이 할당의 크기와 (상대적인) 위치가 컴파일 시에 결정됨을 의미합니다.
char a[32];
char b;
char c;
이들 3개의 변수는 컴파일 시에 할당됩니다.즉, 컴파일러가 컴파일 시에 크기를 계산합니다(고정).변수a
예를 들어 주소 0을 가리키는 메모리 내의 오프셋이 됩니다.b
주소 33을 가리키고c
(얼라인먼트 최적화가 없는 경우)따라서 1Kb의 정적 데이터를 할당해도 코드 내부의 오프셋만 변경되므로 코드 크기가 증가하지는 않습니다.실제 공간은 로드 시 할당됩니다.
실제 메모리 할당은 커널이 이를 추적하고 내부 데이터 구조(프로세스, 페이지 등에 할당되는 메모리 양)를 업데이트해야 하기 때문에 항상 런타임에 발생합니다.차이점은 컴파일러는 사용하는 각 데이터의 크기를 이미 알고 있으며 이는 프로그램이 실행되자마자 할당된다는 것입니다.
또, 상대적인 주소에 대해서도 이야기하고 있는 것에 주의해 주세요.변수가 배치되는 실제 주소는 다릅니다.로드 시 커널은 프로세스를 위해 메모리를 예약합니다(주소 주소).x
실행 파일에 포함된 모든 하드 코드 주소는 다음 순서로 증가합니다.x
바이트, 즉 변수는a
이 예에서는 주소에 있습니다.x
, 주소의 bx+33
기타 등등.
많은 플랫폼에서 컴파일러는 각 모듈 내의 모든 글로벌 할당 또는 스태틱 할당을 3개 이하의 통합 할당(초기화되지 않은 데이터(종종 "bss")용 할당, 초기화된 쓰기 가능한 데이터(종종 "데이터")용 할당 및 고정 데이터("constant")용 할당 및 글로벌 할당 또는 스태틱 할당으로 통합합니다.프로그램 내의 각 유형은 링커에 의해 각 유형에 대해 하나의 글로벌하게 통합됩니다.예를 들어,int
는 4바이트입니다.모듈에는 스태틱 할당이 다음 것밖에 없습니다.
int a;
const int b[6] = {1,2,3,4,5,6};
char c[200];
const int d = 23;
int e[4] = {1,2,3,4};
int f;
링커에 bss는 208바이트, data는 16바이트, const는 28바이트가 필요하다고 알립니다.또한 변수에 대한 참조는 영역 선택기 및 오프셋으로 대체되므로 a, b, c, d 및 e는 각각 bss+0, const+0, bss+4, const+24, data+0 또는 bss+204로 대체됩니다.
프로그램이 링크되면 모든 모듈의 모든 bss 영역이 함께 연결됩니다.데이터 영역과 컨스턴트 영역도 마찬가지입니다.각 모듈에 대해 모든 bss-relative 변수의 주소는 앞의 모든 모듈의 bss 영역 크기만큼 증가합니다(데이터와 const도 마찬가지).따라서 링커가 실행되면 모든 프로그램은 하나의 bss 할당, 하나의 데이터 할당 및 하나의 const 할당이 됩니다.
프로그램이 로드되면 플랫폼에 따라 일반적으로 다음 4가지 중 하나가 발생합니다.
실행 파일은 각 데이터 종류 및 초기화된 데이터 영역에 필요한 바이트 수를 나타냅니다. 이 영역에서는 초기 내용이 검색됩니다.또한 bss-, data 또는 const-relative 주소를 사용하는 모든 명령 목록이 포함됩니다.운영체제 또는 로더는 각 영역에 적절한 공간을 할당하고 필요한 각 명령에 해당 영역의 시작 주소를 추가합니다.
operating system은, 메모리 청크를 할당해, 3 종류의 데이터를 모두 보관 유지해, 그 메모리 청크로의 포인터를 애플리케이션에 제공합니다.정적 데이터 또는 전역 데이터를 사용하는 코드는 해당 포인터에 대해 참조를 해제합니다(많은 경우 포인터는 응용 프로그램의 수명 동안 레지스터에 저장됩니다).
operating system은, 바이너리 코드를 보관 유지하고 있는 것을 제외하고, 최초로 애플리케이션에 메모리를 할당하지 않습니다만, operating system에 적절한 할당을 요구해, 그 할당은 영원히 레지스터에 보존됩니다.
operating system은 처음에는 애플리케이션에 공간을 할당하지 않습니다만, 기동시에 애플리케이션으로부터 적절한 할당이 요구됩니다(상기와 같습니다).어플리케이션에는 메모리가 할당되어 있는 장소를 반영하기 위해서 갱신할 필요가 있는 주소의 명령 리스트가 포함되어 있습니다만, OS 로더에 의해서 어플리케이션이 패치 되는 것이 아니라, 어플리케이션 자체에 패치를 적용하기에 충분한 코드가 포함되어 있습니다.
네 가지 접근 방식 모두 장점과 단점이 있습니다.단, 모든 경우 컴파일러는 임의의 수의 정적 변수를 고정 소수의 메모리 요구로 통합하고 링커는 이들 모든 변수를 소수의 통합된 할당으로 통합합니다.응용 프로그램은 운영 체제 또는 로더로부터 메모리 청크를 수신해야 하지만, 이 큰 청크에서 필요한 모든 개별 변수에 개별 조각을 할당하는 것은 컴파일러와 링커입니다.
질문의 핵심은 다음과 같습니다. "메모리는 컴파일된 파일에서 어떻게 "할당"됩니까?"메모리는 항상 RAM에 모든 가상 메모리 관리 기능과 함께 할당되지 않습니까?메모리 할당은 기본적으로 런타임 개념 아닌가요?"
메모리 할당에는 2개의 다른 개념이 포함되어 있는 것이 문제라고 생각합니다.기본적으로 메모리 할당은 "이 데이터 항목이 이 특정 메모리 청크에 저장됩니다"라고 말하는 프로세스입니다.현대의 컴퓨터 시스템에서는, 다음의 2 단계의 프로세스가 필요합니다.
- 일부 시스템은 항목을 저장할 가상 주소를 결정하는 데 사용됩니다.
- 가상 주소가 물리적 주소에 매핑됩니다.
후자의 프로세스는 순전히 실행 시간이지만, 데이터가 이미 알려진 크기를 가지고 있고 고정된 개수가 필요한 경우 전자는 컴파일 시간에 실행할 수 있습니다.기본적인 동작은 다음과 같습니다.
컴파일러는 다음과 같은 행이 포함된 소스 파일을 확인합니다.
int c;
어셈블러에 대한 출력을 생성하여 변수 'c'에 대해 메모리를 예약하도록 지시합니다.이것은 다음과 같습니다.
global _c section .bss _c: resb 4
어셈블러가 실행될 때 메모리 '세그먼트'(또는 '섹션')의 시작부터 각 항목의 오프셋을 추적하는 카운터를 유지합니다.이것은 파일 전체의 모든 것을 포함하는 매우 큰 '구조'의 일부와 같으며, 현재 실제 메모리가 할당되어 있지 않으며 어디에나 있을 수 있습니다.표에 기재되어 있습니다.
_c
에는 특정 오프셋(세그먼트 시작부터510바이트 등)이 있고 카운터가4씩 증가하기 때문에 다음 변수는 (예를 들어)514바이트가 됩니다.주소가 필요한 모든 코드의 경우_c
출력 파일에 510을 넣을 뿐이며, 출력에 다음 명령어를 포함하는 세그먼트주소가 필요하다는 주의사항이 추가됩니다._c
나중에 추가할 수 있습니다.링커는 어셈블러의 모든 출력 파일을 가져와 검사합니다.각 세그먼트가 겹치지 않도록 각 세그먼트에 대한 주소를 결정하고 명령이 올바른 데이터 항목을 참조하도록 필요한 오프셋을 추가합니다.이러한 초기화되지 않은 메모리가 점유된 경우
c
(어셈블러는 컴파일러가 메모리를 초기화되지 않은 메모리용으로 예약된 이름인 '.bss' 세그먼트에 넣었기 때문에 메모리가 초기화되지 않을 것이라고 들었습니다).어셈블러는 메모리 출력에 얼마를 예약해야 하는지를 나타내는 헤더 필드를 포함하고 있습니다.재배치(통상 재배치)할 수 있지만, 일반적으로는 1개의 특정 메모리 주소로 보다 효율적으로 로드되도록 설계되어 OS는 이 주소로 로드하려고 합니다.현시점에서는, 에 의해서 사용되는 가상 주소가 어느 쪽인지 알 수 있습니다.c
.실제 주소는 프로그램이 실행될 때까지 결정되지 않습니다.그러나 프로그래머의 관점에서 보면 물리 주소는 실제로 중요하지 않습니다.OS는 (프로그램 실행 중에도) 자주 변경될 수 있으며 OS의 주된 목적은 이 주소를 추상화하는 것이기 때문에 물리 주소가 무엇인지조차 알 수 없습니다.
받아들여진 답변에는 매우 좋은 설명이 있다.혹시나 해서 도움이 될 것 같은 링크를 올립니다.https://www.tenouk.com/ModuleW.html
N바이트를 차지하는 변수를 스택에 추가해도 (필요에 따라) 빈의 크기가 N바이트 증가하지 않습니다.실제로 대부분의 경우 몇 바이트만 추가됩니다.
먼저 코드에 1000자를 추가하면 빈의 크기가 선형으로 증가하는 예를 보여 줍니다.
1k가 1000자의 문자열일 경우 다음과 같이 선언됩니다.
const char *c_string = "Here goes a thousand chars...999";//implicit \0 at end
그리고 나서 당신은vim your_compiled_bin
어디선가 그 끈을 볼 수 있을 겁니다.이 경우 실행 파일은 문자열 전체를 포함하므로 1k 더 커집니다.
단, 배열을 할당하는 경우int
s,char
또는long
를 스택에 배치하여 루프로 할당합니다.
int big_arr[1000];
for (int i=0;i<1000;++i) big_arr[i] = some_computation_func(i);
그러면 안 돼요. 쓰레기통이 늘어나지 않아요.타고1000*sizeof(int)
컴파일 시 할당이란 현재 알게 된 것을 의미합니다(고객님의 코멘트에 근거해).컴파일된 빈에는 실행 시 필요한 기능/블록의 메모리 용량과 어플리케이션에 필요한 스택사이즈 정보가 포함되어 있습니다.시스템이 bin을 실행하고 프로그램이 프로세스가 될 때 할당됩니다(bin의 실행은 다음과 같은 프로세스입니다.무슨 말인지 아시겠죠.)
물론 여기서 전체 그림을 그리는 것은 아닙니다.bin에는 bin에 실제로 필요한 스택의 크기에 대한 정보가 포함되어 있습니다.이 정보(특히)에 근거해, 시스템은 스택이라고 불리는 메모리 청크를 예약합니다.이것에 의해, 프로그램은 어느 정도 프리 리치를 실시합니다.스택 메모리는 프로세스(빈 실행 결과)가 시작될 때 시스템에 의해 계속 할당됩니다.다음으로 스택메모리를 관리합니다.함수 또는 루프(모든 유형의 블록)가 호출/실행되면 해당 블록에 대한 로컬 변수가 스택에 푸시되고 다른 함수/블록에서 사용하기 위해 해당 변수가 제거됩니다(즉, 스택메모리는 "자유").그래서 선언한다.int some_array[100]
빈에 몇 바이트의 추가 정보만 추가하면 X 함수가 필요함을 시스템에 알립니다.100*sizeof(int)
+ 부기 공간을 추가로 확보합니다.
실행 파일은 정적 변수에 할당하는 공간을 나타냅니다.이 할당은 실행 파일을 실행할 때 시스템에 의해 수행됩니다.따라서 1kB 정적 변수는 실행 파일의 크기를 1kB로 늘리지 않습니다.
static char[1024];
물론 이니셜라이저를 지정하지 않는 한:
static char[1024] = { 1, 2, 3, 4, ... };
따라서 실행 파일에는 '머신 언어'(CPU 명령) 외에 필요한 메모리 레이아웃에 대한 설명이 포함됩니다.
메모리는 다양한 방법으로 할당할 수 있습니다.
- 응용 프로그램 힙(프로그램 시작 시 OS에 의해 앱에 할당되는 전체 힙)
- (더 많은 정보를 얻을 수 있도록)
- 가비지 콜렉터 제어 힙(위 양쪽과 동일)에 있습니다.
- (스택 오버플로를 얻을 수 있도록)
- 바이너리의 코드/데이터 세그먼트에 예약(예약 가능)
- 리모트 플레이스(파일, 네트워크 - 해당 메모리에 대한 포인터가 아닌 핸들을 수신)
이제 당신의 질문은 "컴파일 시 할당된 메모리"가 무엇인지입니다.확실히 이것은 바이너리 세그먼트 할당 또는 스택 할당, 또는 경우에 따라서는 힙 할당 중 하나를 언급해야 하는 잘못된 표현일 뿐이지만, 이 경우 할당은 보이지 않는 컨스트럭터 호출에 의해 프로그래머의 눈에 띄지 않게 숨겨집니다.또는 메모리는 힙에 할당되어 있지 않지만 스택 또는 세그먼트 할당에 대해서는 모른다고 말하고 싶었던 사람일 수도 있습니다.(혹은 그런 세부사항을 설명하고 싶지 않았습니다.)
그러나 대부분의 경우 할당되는 메모리의 양은 컴파일 시에 알 수 있다고 말하고 싶을 뿐입니다.
이진 크기는 메모리가 앱의 코드 또는 데이터 세그먼트에 예약되어 있는 경우에만 변경됩니다.
맞아요.메모리는 실제로 로드 시, 즉 실행 파일을 (가상) 메모리에 가져올 때 할당(페이징)됩니다.메모리도 그 순간에 초기화할 수 있습니다.컴파일러는 메모리 맵만 만듭니다.[그런데 로드 시 스택 및 힙 공간도 할당됩니다!]
좀 뒤로 물러나야 할 것 같아요.컴파일 시 할당된 메모리...그게 무슨 뜻이죠?즉, 아직 제조되지 않은 칩의 메모리, 즉 아직 설계되지 않은 컴퓨터의 메모리가 어떤 식으로든 예약되어 있다는 의미일까요?아니, 시간 여행이라든가 우주를 조종할 컴파일러는 없어
따라서 컴파일러는 실행 시 메모리를 할당하는 명령을 생성해야 합니다.그러나 올바른 각도에서 보면 컴파일러가 모든 명령을 생성합니다.그러면 어떤 차이가 있을까요?차이점은 컴파일러가 결정을 내리고 실행 시 코드가 결정을 변경하거나 수정할 수 없다는 것입니다.컴파일 시 50바이트가 필요하다고 판단되면 실행 시 60바이트를 할당하도록 결정할 수 없습니다.이 결정은 이미 내려진 것입니다.
어셈블리 프로그래밍을 배우면 데이터, 스택 및 코드 등에 대한 세그먼트를 분할해야 한다는 것을 알 수 있습니다.데이터 세그먼트는 문자열과 숫자가 있는 곳입니다.코드 세그먼트는 코드가 존재하는 곳입니다.이러한 세그먼트는 실행 가능한 프로그램에 포함되어 있습니다.물론 스택 사이즈도 중요하지만...스택 오버플로를 원하지 않을 것입니다.
따라서 데이터 세그먼트가 500바이트인 경우 프로그램에는 500바이트 영역이 있습니다.데이터 세그먼트를 1500바이트로 변경하면 프로그램 크기가 1000바이트 커집니다.데이터는 실제 프로그램으로 통합됩니다.
고급 언어를 컴파일할 때 이런 일이 벌어집니다.실제 데이터 영역은 실행 가능한 프로그램으로 컴파일될 때 할당되어 프로그램의 크기가 커집니다.이 프로그램은 메모리도 바로 요구할 수 있는데, 이것이 다이내믹 메모리입니다.RAM에 메모리를 요구할 수 있으며 CPU는 메모리를 사용할 수 있도록 메모리를 제공합니다.사용자는 메모리를 놓으면 가비지 컬렉터가 메모리를 CPU로 다시 해방합니다.필요에 따라서, 적절한 메모리 매니저에 의해서 하드 디스크로 스왑 할 수도 있습니다.이러한 기능은 고급 언어로 제공됩니다.
이 개념들을 몇 가지 도표로 설명하겠습니다.
컴파일시에 메모리를 할당할 수 없는 것은 확실합니다.하지만 실제로 컴파일 시간에 무슨 일이 일어나는지.
여기 설명이 있다.예를 들어 프로그램에는 x, y, z 및 k 변수가 4개 있다고 가정합니다.컴파일 시에는 단순히 메모리 맵을 만듭니다.여기서 이들 변수의 위치가 서로 확인됩니다.이 그림이 그것을 더 잘 설명해 줄 것이다.
메모리에서 실행 중인 프로그램이 없다고 상상해 보십시오.이것은 큰 빈 직사각형으로 보여 줍니다.
다음으로 이 프로그램의 첫 번째 인스턴스가 실행된다.다음과 같이 시각화할 수 있습니다.이때 실제로 메모리가 할당됩니다.
이 프로그램의 두 번째 인스턴스가 실행 중일 때 메모리는 다음과 같습니다.
그리고 세번째는..
기타 등등.
이 시각화가 이 개념을 잘 설명해주길 바랍니다.
컴파일러가 수행하는 많은 작업 중 하나는 섹션 아래에 SYMBOL TAB(심볼 테이블)을 만들고 유지하는 것입니다.sym tab)을 클릭합니다.이것은 개발자의 눈이 아닌 데이터 구조(목록, 트리 등)를 사용하는 컴파일러에 의해 작성 및 관리됩니다.개발자가 요청한 액세스 요청은 여기서부터 시작됩니다.
기호 테이블에 대해서는 기호 이름과 간격띄우기 두 열만 알면 됩니다.
기호 이름 열에는 변수 이름이 있고 간격띄우기 열에는 간격띄우기 값이 있습니다.
예를 들면, 다음과 같습니다.
int a , b , c ;
이제 레지스터 Stack_Pointer(sp)가 스택메모리의 상부를 가리키고 있는 것을 알 수 있습니다.sp = 1000이라고 합니다.
이제 기호 이름 열에는 a, b, c의 세 가지 값이 포함됩니다.변수 a가 스택메모리의 맨 위에 있음을 다시 한 번 알려드립니다.
따라서 A의 등가 오프셋 값은 0이 됩니다.(Compile Time Offset_Value)
그러면 b와 그에 상응하는 오프셋 값은 1이 됩니다.(Compile Time Offset_Value)
그러면 c와 그에 상응하는 오프셋 값은 2가 됩니다.(Compile Time Offset_Value)
이제 A의 물리적 주소(또는) 런타임 메모리 주소 = (sp + offset_value of a) = (1000 + 0) = 1000을 계산하는 중입니다.
이제 b의 물리적 주소(또는) 런타임 메모리 주소 = (sp - offset_value of b) = (1000 - 1) = 996을 계산하는 중입니다.
이제 c의 물리적 주소(또는) 런타임 메모리 주소 = (sp - offset_value of c) = (1000 - 2) = 992를 계산하는 중입니다.
따라서 컴파일 시에는 오프셋 값만 갖게 되며 실제 물리 주소가 계산되는 것은 실행 시뿐입니다.
주의: Stack_Pointer 값은 프로그램이 로드된 후에만 할당됩니다.포인터 산술은 Stack_Pointer 레지스터와 변수 오프셋 사이에서 발생하며 변수의 물리 주소를 계산합니다.
"POINTERS AND POINTER ARITHMETIC, WAY OF THE PROGRAMMING WORLD"
언급URL : https://stackoverflow.com/questions/21350478/what-does-memory-allocated-at-compile-time-really-mean
'sourcecode' 카테고리의 다른 글
입력에 초점을 맞추고 @click을 하면 Vue.js 입력 제안 표시 (0) | 2022.08.13 |
---|---|
Vue를 사용하여 CSS를 무한 애니메이션화하는 방법 (0) | 2022.08.13 |
종속성 주입을 통해 Vue.JS Vuex 저장 및 my api (0) | 2022.08.13 |
모듈과 함께 vuexfire를 사용할 때 돌연변이를 처리하는 방법은 무엇입니까? (0) | 2022.08.13 |
폴더에서 모든 Vue 구성 요소를 가져오려면 어떻게 해야 합니까? (0) | 2022.08.13 |