programing

C에서 데이터 섹션과 bss 섹션의 차이

megabox 2023. 6. 8. 19:35
반응형

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바이트입니다.하지만, 우리가 돌이켜보면..bssheader, 열이 .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.oC 런타임의 일부입니다.


마지막으로, 우리는 이 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

반응형