데이터 영역과 .bss 영역의 차이

kkb의 이미지

전역변수나 static 변수를 선언할 때 초기값이 있으면 데이터 영역에 할당되고
초기값이 없으면 .bss 영역에 할당된다고 알고 있습니다

그러나 .bss 영역에 할당되는 변수도 어차피 (쓰레기 값이 아닌) 디폴트 값으로 초기화됩니다

① 그러면 데이터 영역의 변수와 .bss 영역의 변수 장단점이 무엇인가요?
(속도 차이가 있다고 들은 적이 있는 것 같습니다만...)

② 그리고 그러면 전역변수나 static 변수를 선언할 때
초기값을 주는 것이 좋은가요? 안주는 것이 좋은가요?

③ 전역변수는 지역변수에 비해 되도록이면 사용하지 않는 게 좋은가요?

int main(void)
{
	char *ch = "Hello, world!";
...

④ 위의 데이터는 어느 영역에 저장되나요?
ch 변수는 지역 변수니까 스택 영역에 저장되겠지만
ch 변수 말고 저 문자열 데이터는 어디에 저장되어서 그 주소를 지역변수인 ch 변수에 저장하나요?
코드 영역인가요? 데이터 영역인가요? .bss 영역인가요?

(때때로 데이터 영역과 BSS 영역을 합쳐서 데이터 영역이라고 설명하기도 하는 것을 보았습니다
여기서는 데이터 영역을 BSS 영역을 제외한 영역으로 정의하여 설명해주셨으면 좋겠습니다)

jeongheumjo의 이미지

저도 bss 영역과 데이타영역의 차이에 대해 구글링을 해서 알게 되었네요..

http://shinluckyarchive.tistory.com/159

제가 찾은 블로그인데 설명이 잘 되어있습니다.

① 그러면 데이터 영역의 변수와 BSS 영역의 변수 장단점이 무엇인가요?
(속도 차이가 있다고 들은 적이 있는 것 같습니다만...)
>> 위 블로그를 보면 속도 차이가 있겠다 싶습니다. BSS영역에 실제 변수가 차지할 공간이 할당되지 않으므로 바이너리 사이즈가 그만큼 작아지겠습니다. 바이너리 크기가 절약된다는 것은 임베디드 시스템에서는 의미가 있는 차이라고 봅니다.(마지막 문장은 제 짐작일 뿐이네요.. 더 전문가 되시는 어느 분이 충분히 반론하실 수 있는) 그런데 작은 바이너리가 더 큰 바이너리에 비해 로딩속도가 더 빠른가 하는 것은 잘 모르겠습니다. 이것도 임베디드 시스템에서가 관건인데 저는 임베디드 시스템 전문가는 아니라서요... 임베디드 시스템이 아니라면 사실 이런 차이를 고려하는 것은 큰 의미 없을 것이라 생각합니다.

② 그리고 그러면 전역변수나 static 변수를 선언할 때
초기값을 주는 것이 좋은가요? 안주는 것이 좋은가요?
>> 블로그를 통해보면 초기값을 안주면 .bss 섹션에 들어가고 초기값을 주면 .data 섹션에 들어가는 것 같습니다.
.bss 섹션에 넣어서 바이너리 사이즈를 줄이고 싶으면 초기값을 안주면 되고 .data 섹션에 넣으려면 초기값을 코딩시 주면 될 것 같은데,
예를 들어 사이즈가 큰 배열(예전 임베디드 시스템에서는 주로 폰트 데이타)을 생각한다면 중요한 의미가 있을 거라 봅니다. 그 폰트 크기가 100kB 이상된다면, 간단히 생각하면 .data 영역에 넣어야 할 것 같네요.. .bss 영역에 넣더라도 그 초기값을 .text 섹션에서 복사해 넣는 방식이라면 쓸데없이 .text 섹션을 낭비하는 것일 수도 있으니까요..
아... 이 부분도 역시 아주 재미있는 내용이 있네요,.. 폰트 데이터와 같은 경우 고정되는 바이너리와 분리하는 구조를 흔히 씁니다. 일종의 OCP(Open-Closed Principle) 라고 볼 수도 있겠습니다. 폰트데이타와 같은 것은 변경이 자주 발생하는 것이죠. 새로운 폰트가 제품 릴리즈 이후에 출시될 수도 있고요, 하지만 폰트가 바뀌었을 때 코드를 매번 수정한다면 매우 귀찮은 일이지요. 따라서 폰트 데이타를 바이너리 로딩시에 .bss 섹션으로부터 읽어들이도록 함으로써 바이너리를 폰트 데이타와 분리하는 방식을 취하는 것 같습니다. 이점은 잦은 폰트 데이터 변경시에 코드는 변경할 필요가 없다는 OCP 의 장점을 가질 수 있다는 것이죠... 이 부분 제가 뜬구름 잡듯이 설명드렸습니다. 실상 저도 잘 모르는 내용이거든요. 임베디드 시스템에서는 아주 중요한 내용이라는 것만 말씀드릴 수 있겠습니다.

③ 전역변수는 지역변수에 비해 되도록이면 사용하지 않는 게 좋은가요?

int main(void)
{
char *ch = "Hello, world!";
...

>> 전역변수가 나쁘다는 것은 회사에서는 선배들이 누누히 강조하는 것입니다. 모든 버그들의 가장 빈도수 높은 원흉 또한 읽기 힘든 코드가 되도록 하는 1등 공신.. 이는 높은 수준에서으 이유이고요. 낮은 수준에서는 역시 임베디드 시스템인 경우 메모리 맵을 어떻게 설계했는가 그래서 각 섹션의 크기가 어느 정도 확보되어있는가에 따라 결정될 것 같습니다. 임베디드 시스템에서는 고정된 메모리 맵에 따라 프로그램이 실행되는데 그 각각의 공간이 그리 넉넉하지 않거든요. 그래서 이 경우는 메모리 맵을 디자인하는 시스템 엔지니어의 의견이 중요하다고 생각합니다.

④ 위의 데이터는 어느 영역에 저장되나요?
ch 변수는 지역 변수니까 스택 영역에 저장되겠지만
ch 변수 말고 저 문자열 데이터는 어디에 저장되어서 그 주소를 지역변수인 ch 변수에 저장하나요?
코드 영역인가요? 데이터 영역인가요? BSS 영역인가요?
>>변수 ch는 당연히 스택이고요.. 쉽죠. 스트링 "Hello, world!" 는 힙이라고 생각합니다.

재미있는 질문 재미있게 찾아보았습니다.
kldp 에서는 다른 사람의 질문을 고민해볼 수 있어서 좋습니다.
제가 잘못 설명한 부분있다면 고쳐주세요..

참고로, .bss 섹션의 동작방식과 여타 메모리맵의 구성은 각 컴파일러마다 조금씩 다른 것 같습니다.
예를 들어 암 컴파일러 에서는 .bss 섹션이 ZI 섹션이라는 영역이었습니다. .bss 섹션은 아마도 gcc 에서의 얘기인 것 같은데요,...
ZI섹션은 초기값이 모두 0으로 정해지는 .data 섹션이었습니다.

jeongheumjo의 이미지

제가 알려드린 블로그는 믿을 만한 정보를 간단히 담고 있지만
제가 설명드린 것은 오류가 많은 것 같습니다. 제 의견은 그냥 의견으로만 생각해 주세요... 정확한 정보가 절대 아닙니다.
특히 아랫 부분 자신이 없네요..
>>변수 ch는 당연히 스택이고요.. 쉽죠. 스트링 "Hello, world!" 는 힙이라고 생각합니다.

익명 사용자의 이미지

runtime에 literal constant가 생성되는 게 아니라 static time에 이미 executable에 들어있어야 하니까요.

.data 또는 .text인 것 같습니다. 아마도 .text 섹션이 아닐까요, read only니까요.

kkb의 이미지

답변 감사합니다

제가 직접 디버깅해보니
.text 섹션에 저장됩니다 :)

익명 사용자의 이미지

① 그러면 데이터 영역의 변수와 BSS 영역의 변수 장단점이 무엇인가요?
(속도 차이가 있다고 들은 적이 있는 것 같습니다만...)

[잘 모릅니다 패스 ]

② 그리고 그러면 전역변수나 static 변수를 선언할 때
초기값을 주는 것이 좋은가요? 안주는 것이 좋은가요?

[전역 , static을 떠나서 모든 변수는 초기값 주는게 좋음
최초의 가비지값이 들어가 있기 때문이죠 요즘 PC사항다 좋습니다.]

③ 전역변수는 지역변수에 비해 되도록이면 사용하지 않는 게 좋은가요?

int main(void)
{
char *ch = "Hello, world!";
...

[ 전역변수는 속도도 속도지만 여럿이 개발할때 알아먹기 힘듭니다
파라메터를 함수마다 call by value로 왜 던질까요? 전역쓰면되지
다 유지보수하고 같이하는사람들 위함이죠]

④ 위의 데이터는 어느 영역에 저장되나요?

[TC든 ,,,gcc -S 옵션주고 컴파일해보면 됩니다]

klutzy의 이미지

0) bss는 C 표준에서는 나오지 않습니다. 표준에서는 초기화 안 하면 0으로 처리한다는 것밖에 없죠. bss는 OS/실행파일 포맷에 대한 부분입니다. ELF를 기준으로 설명할게요.

1) 예를 들어서 다음과 같은 변수가 함수 바깥에 있다고 하면:

int a[100000] = {1,};

컴파일해보면 실행 파일이 약 400kB정도 나오는 것을 볼 수 있습니다. 그렇다면 초기화를 하지 않는다면:

int a[100000];

이제 컴파일해보면 해당 배열은 파일 용량을 차지하지 않습니다.

bss는 초기화가 되지 않은 공간을 한곳에 모아두는 곳입니다. 어차피 0으로 초기화할 변수들이라면 한 곳에 몰아두고 그 영역 전체를 0으로 만드는 게 편하니까요.

2) 제 경우는 위의 코드에서 {0,}으로 초기화해도 역시 마찬가지로 용량을 차지하지 않습니다. 0으로 초기화해야 할 때 어디로 들어갈지는 컴파일러가 알아서 해 줄 겁니다. 컴파일러가 좋다면요.

더 자세한 설명은 http://stackoverflow.com/questions/610682/bss-section-in-elf-file 쪽을 참고하세요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.