C와 C++ 컴파일러가 명시적으로 초기화된 글로벌 변수와 기본 초기화된 글로벌 변수를 서로 다른 세그먼트에 배치하는 이유는 무엇입니까?
C 프로그램의 메모리 레이아웃에 대한 이 멋진 글을 읽고 있었습니다.기본 초기화된 전역 변수는 BSS 세그먼트에 존재하며 전역 변수에 값을 명시적으로 제공하면 데이터 세그먼트에 존재합니다.
저는 이 동작을 조사하기 위해 C와 C++의 다음 프로그램을 테스트했습니다.
#include <iostream>
// Both i and s are having static storage duration
int i; // i will be kept in the BSS segment, default initialized variable, default value=0
int s(5); // s will be kept in the data segment, explicitly initialized variable,
int main()
{
std::cout<<&i<<' '<<&s;
}
출력:
0x488020 0x478004
따라서 출력에서 보면 변수 i와 s 모두 완전히 다른 세그먼트에 있는 것처럼 보입니다.하지만 변수 S에서 이니셜라이저(본 프로그램에서는 초기값 5)를 제거한 후 프로그램을 실행하면 다음과 같은 출력이 나옵니다.
출력:
0x488020 0x488024
따라서 출력에서 보면 변수 i와 s가 모두 동일한(이 경우 BSS) 세그먼트에 있는 것처럼 보입니다.
이 동작은 C에서도 마찬가지입니다.
#include <stdio.h>
int i; // i will be kept in the BSS segment, default initialized variable, default value=0
int s=5; // s will be kept in the data segment, explicitly initialized variable,
int main(void)
{
printf("%p %p\n",(void*)&i,(void*)&s);
}
출력:
004053D0 00403004
따라서 다시 출력(변수의 주소를 조사하는 것을 의미)을 보면 변수 i와 s 모두 완전히 다른 세그먼트에 존재한다고 말할 수 있습니다.하지만 변수 S에서 이니셜라이저(본 프로그램에서는 초기값 5)를 제거한 후 프로그램을 실행하면 다음과 같은 출력이 나옵니다.
출력:
004053D0 004053D4
따라서 출력에서 보면 변수 i와 s가 모두 동일한(이 경우 BSS) 세그먼트에 있는 것처럼 보입니다.
C와 C++ 컴파일러가 명시적으로 초기화된 글로벌 변수와 기본 초기화된 글로벌 변수를 서로 다른 세그먼트에 배치하는 이유는 무엇입니까?기본 초기화된 변수와 명시적으로 초기화된 변수 사이에 전역 변수가 어디에 있는지에 대한 차이가 있는 이유는 무엇입니까?제가 틀리지 않았다면, C와 C++ 표준은 스택, 힙, 데이터 세그먼트, 코드 세그먼트, BSS 세그먼트 등 구현에 특화된 모든 것에 대해 절대 말하지 않습니다.그렇다면 C++ 구현에서 명시적으로 초기화된 변수와 기본 초기화된 변수를 서로 다른 세그먼트에 저장하는 대신 동일한 세그먼트에 저장할 수 있습니까?
C 언어나 C++ 언어 모두 "세그먼트"라는 개념을 가지고 있지 않으며, 모든 OS가 그런 것도 아니기 때문에 질문은 플랫폼과 컴파일러에 의존할 수밖에 없습니다.
즉, 일반적인 구현은 초기화된 변수와 초기화되지 않은 변수를 다르게 취급할 것입니다.주요 차이점은 초기화되지 않은(또는 기본 0-초기화된) 데이터를 컴파일된 모듈로 실제로 저장할 필요가 없고, 실행 시간에 나중에 사용하기 위해 선언/예약된 데이터만 저장할 수 있다는 것입니다.실질적인 "세그먼트" 용어에서 초기화된 데이터는 바이너리의 일부로 디스크에 저장되는 반면, 초기화되지 않은 데이터는 그렇지 않으며, 대신 선언된 "예약"을 충족하기 위해 시작할 때 할당됩니다.
정말 짧은 대답은 "공간을 덜 차지하기 때문"입니다.(다른 사람들이 언급한 것처럼, 컴파일러는 이것을 할 필요가 없습니다!)
실행 파일에서,data
섹션에는 해당 값이 상대적인 위치에 저장된 데이터가 포함됩니다.이는 초기화된 데이터의 각 바이트에 대해 해당 데이터 섹션에 1바이트가 포함됨을 의미합니다.
초기화된 전역이 0인 경우 0을 많이 저장할 이유가 없습니다.대신 전체 데이터 집합의 크기를 단일 크기 값에 저장합니다.그래서 4132 바이트의 0을 저장하는 대신에data
secondon, "BSS는 4132 바이트 길이이다"라는 것이 있을 뿐입니다 - 그리고 그것이 0이 되도록 설정하는 것은 OS/runtime에 달려있습니다. - 경우에 따라서는 컴파일러의 런타임이memset(BSSStart, 0, BSSSize)
또는 유사한.예를 들어 리눅스의 경우 프로세스가 생성될 때 어차피 모든 "사용하지 않은" 메모리가 0으로 채워지므로 BSS를 0으로 설정하는 것은 애초에 메모리를 할당하는 문제일 뿐입니다.
물론 실행 파일이 짧아지면 다음과 같은 여러 이점이 있습니다.하드 디스크에 차지하는 공간 감소, 로딩 시간 단축 [OS가 할당된 메모리를 0으로 미리 채우면 추가 보너스], 컴파일러/링커가 데이터를 디스크에 쓸 필요가 없으므로 컴파일 시간이 단축됩니다.
그래서 이것에는 완전히 현실적인 이유가 있습니다.
BSS는 정의상 다른 세그먼트가 아니라 데이터 세그먼트의 일부입니다.
C 및 C++에서 명시적 초기화기 없이 정적으로 할당된 개체는 0으로 초기화됩니다. 구현은 또한 0-값 비트로만 구성된 값으로 초기화된 정적으로 할당된 변수와 상수를 BSS 섹션에 할당할 수 있습니다.
BSS에 저장하는 이유는 초기화되지 않은 값 또는 기본값을 가진 변수 유형을 데이터 세그먼트에 배치된 변수가 아닌 이진 파일의 공간을 낭비하지 않고 런타임에 얻을 수 있기 때문입니다.
언급URL : https://stackoverflow.com/questions/34367781/why-do-c-and-c-compilers-place-explicitly-initialized-and-default-initialized
'source' 카테고리의 다른 글
크롬 확장을 테스트하는 방법은? (0) | 2023.10.29 |
---|---|
모든 경로에서 Can Activate guard를 신청하는 방법은? (0) | 2023.10.29 |
앱이 다시 시작되지 않고 다시 시작됨 (0) | 2023.10.29 |
컨테이너의 나머지 너비를 채우는 스타일 입력 요소 (0) | 2023.10.29 |
구조 부재를 오프셋으로 가져오거나 설정하려면 어떻게 해야 합니까? (0) | 2023.10.29 |