C에서 데이터 섹션과 bss 섹션의 차이
를 통해 객체 파일의 분해를 확인할 때readelf
나는 봅니다.data
그리고bss
세그먼트에 동일한 오프셋 주소가 포함되어 있습니다.그data
섹션에는 초기화된 전역 및 정적 변수가 포함됩니다. BSS에는 초기화되지 않은 전역 및 정적 변수가 포함됩니다.
1 #include<stdio.h>
2
3 static void display(int i, int* ptr);
4
5 int main(){
6 int x = 5;
7 int* xptr = &x;
8 printf("\n In main() program! \n");
9 printf("\n x address : 0x%x x value : %d \n",(unsigned int)&x,x);
10 printf("\n xptr points to : 0x%x xptr value : %d \n",(unsigned int)xptr,*xptr);
11 display(x,xptr);
12 return 0;
13 }
14
15 void display(int y,int* yptr){
16 char var[7] = "ABCDEF";
17 printf("\n In display() function \n");
18 printf("\n y value : %d y address : 0x%x \n",y,(unsigned int)&y);
19 printf("\n yptr points to : 0x%x yptr value : %d \n",(unsigned int)yptr,*yptr);
20 }
출력:
SSS:~$ size a.out
text data bss dec hex filename
1311 260 8 1579 62b a.out
위 프로그램에서 초기화되지 않은 데이터는 없지만 BSS가 8바이트를 차지했습니다.왜 8바이트를 차지합니까?또한 오브젝트 파일을 분해할 때,
편집됨:
[ 3] .data PROGBITS 00000000 000110 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000110 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 00000000 000110 0000cf 00 A 0 0 4
data
,rodata
그리고.bss
오프셋 주소가 동일합니다.그것은 그것을 의미합니까?rodata
,data
그리고.bss
같은 주소를 참조하시겠습니까?데이터 섹션, 로드 데이터 섹션 및 bss 섹션에 동일한 주소의 데이터 값이 포함되어 있습니까? 그렇다면 데이터 섹션, bss 섹션 및 로드 데이터 섹션을 어떻게 구분합니까?
그.bss
프로그램이 메모리에 로드될 때 섹션은 모두 0이 되도록 보장됩니다.따라서 초기화되지 않았거나 0으로 초기화된 모든 글로벌 데이터는.bss
부분.예:
static int g_myGlobal = 0; // <--- in .bss section
이것에 대한 좋은 부분은,.bss
섹션 데이터는 디스크의 ELF 파일에 포함될 필요가 없습니다. 즉, 파일에 0의 전체 영역이 없습니다..bss
섹션)을 클릭합니다.대신 로더는 섹션 헤더를 통해 다음을 위해 할당할 양을 알고 있습니다..bss
프로그램에 제어권을 넘겨주기 전에 섹션을 0으로 설정합니다.
주의:readelf
출력:
[ 3] .data PROGBITS 00000000 000110 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000110 000000 00 WA 0 0 4
.data
로 표시됩니다.PROGBITS
즉, ELF 파일에 로더가 메모리로 읽어들여야 하는 프로그램 데이터의 "비트"가 있다는 것입니다. .bss
반면에 표시되어 있습니다.NOBITS
즉, 파일에 로드의 일부로 메모리에 읽을 필요가 없습니다.
예:
// bss.c
static int g_myGlobal = 0;
int main(int argc, char** argv)
{
return 0;
}
다음으로 컴파일$ gcc -m32 -Xlinker -Map=bss.map -o bss bss.c
다음을 사용하여 섹션 머리글 보기$ readelf -S bss
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
:
[13] .text PROGBITS 080482d0 0002d0 000174 00 AX 0 0 16
:
[24] .data PROGBITS 0804964c 00064c 000004 00 WA 0 0 4
[25] .bss NOBITS 08049650 000650 000008 00 WA 0 0 4
:
이제 기호 테이블에서 변수를 찾습니다.$ readelf -s bss | grep g_myGlobal
37: 08049654 4 OBJECT LOCAL DEFAULT 25 g_myGlobal
참고:g_myGlobal
섹션 25의 일부로 표시됩니다.섹션 머리글을 다시 보면 25는.bss
.
당신의 진짜 질문에 답하기 위해:
여기 위 프로그램에서 초기화되지 않은 데이터는 없지만 BSS가 8바이트를 차지했습니다.왜 8바이트를 차지합니까?
제 예를 계속해서, 우리는 섹션 25에서 기호를 참조하십시오.
$ readelf -s bss | grep 25
9: 0804825c 0 SECTION LOCAL DEFAULT 9
25: 08049650 0 SECTION LOCAL DEFAULT 25
32: 08049650 1 OBJECT LOCAL DEFAULT 25 completed.5745
37: 08049654 4 OBJECT LOCAL DEFAULT 25 g_myGlobal
세 번째 열은 크기입니다.예상되는 4바이트가 표시됩니다.g_myGlobal
1바이트 1바이트입니다.completed.5745
이것은 아마도 C 런타임 초기화의 어딘가에서 온 함수 정적 변수일 것입니다. 기억하세요, 많은 "사물"이 이전에 발생합니다.main()
항상 호출됩니다.
+1=5바이트입니다.하지만, 우리가 돌이켜보면..bss
header, 열이 .Al
는 4입니다. 즉, 섹션 정렬입니다. 이 섹션은 로드될 때 항상 4바이트의 배수가 됩니다. 5의 배수인 5의 배수인 8의 배수입니다..bss
섹션은 8바이트입니다.
또한 링커에 의해 생성된 맵 파일을 확인하여 최종 출력에서 어떤 개체 파일이 배치되었는지 확인할 수 있습니다.
.bss 0x0000000008049650 0x8
*(.dynbss)
.dynbss 0x0000000000000000 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
*(.bss .bss.* .gnu.linkonce.b.*)
.bss 0x0000000008049650 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
.bss 0x0000000008049650 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crti.o
.bss 0x0000000008049650 0x1 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtbegin.o
.bss 0x0000000008049654 0x4 /tmp/ccKF6q1g.o
.bss 0x0000000008049658 0x0 /usr/lib/libc_nonshared.a(elf-init.oS)
.bss 0x0000000008049658 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtend.o
.bss 0x0000000008049658 0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crtn.o
다시 세 번째 열은 크기입니다.
4바이트가 표시됩니다..bss
에서 왔습니다./tmp/ccKF6q1g.o
이 사소한 예에서, 우리는 그것이 우리의 bss.c 파일의 컴파일에서 나온 임시 객체 파일이라는 것을 알고 있습니다.나머지 1바이트는 다음에서 왔습니다.crtbegin.o
C 런타임의 일부입니다.
마지막으로, 우리는 이 1바이트 미스터리 bss 변수가 출처라는 것을 알고 있기 때문입니다.crtbegin.o
그리고 그것의 이름은completed.xxxx
명본은입니다.completed
아마도 어떤 기능 안에 있는 정전기일 겁니다.보면 범인을 찾을 수 있습니다.static _Bool completed
쪽에의 __do_global_dtors_aux()
.
정의에 따르면 bss 세그먼트는 프로그램이 시작될 때 메모리에서 일정한 위치를 차지하지만 디스크 공간은 필요하지 않습니다.변수를 채우려면 변수를 정의해야 합니다.
int bigvar_in_bss[16300];
int var_in_data[5] = {1,2,3,4,5};
도 있습니다..bss
공유 예:libc.so
) "그들만의 것"이 있을 수 있습니다..bss
"
파일 오프셋과 메모리 주소는 쉽게 연관되지 않습니다.
ELF 사양에 대한 자세한 내용 읽기, 사용/proc/
: 예:cat /proc/self/maps
의주 이 표시됩니다.cat
프로세스(해당 명령을 실행 중)proc(5)도 읽습니다.
언급URL : https://stackoverflow.com/questions/16557677/difference-between-data-section-and-the-bss-section-in-c
'programing' 카테고리의 다른 글
루비에서 '예외 => e를 구출하는 것은 왜 나쁜 스타일인가요? (0) | 2023.06.08 |
---|---|
Android:소프트 키보드가 내 보기를 위로 밀어 올리는 것을 방지하려면 어떻게 해야 합니까? (0) | 2023.06.08 |
Shiny에서 '최대 업로드 크기 초과' 제한을 변경하고 사용자 파일 입력을 저장하는 방법은 무엇입니까? (0) | 2023.06.08 |
ReDim Preserve는 무엇을 합니까? (0) | 2023.06.08 |
Vue + Vuex + Phaser 반응형 통화에서 '이' 스코프가 손실됨 (0) | 2023.06.08 |