[c언어]지역변수를 위한 로칼스택 할당 사이즈에 대한 문의

choco6의 이미지

예를 들어 다음과 같은 함수를 테스트하는 경우,

void func(void)
{
char buf1[3];
}

x86 기반의 linux 2.6에서 gcc로 컴파일한다면, 제 상식으로는 buf1을 위해서 로칼 스택에 4바이트가 할당될 것이라 생각했습니다. 그런데 gdb로 확인하면

(gdb) disassem func
Dump of assembler code for function func:
0x8048460 <func>: push %ebp
0x8048461 <func+1>: mov %esp,%ebp
0x8048463 <func+3>: sub $0x18,%esp
0x8048466 <func+6>: leave
0x8048467 <func+7>: ret

보다시피 컴파일러는 buf1을 위해서 24바이트(18h) 스택 공간을 할당하는 것을 볼 수 있습니다. 그런데 buf1[4]로 하면 4바이트가 할당이 되더군요. 그리고 buf1[5]로 하면 다시 24바이트가 할당이 됩니다.
이렇게 linux에서 일관적으로 보이지 않게 로칼 스택을 할당하는 이유가 무엇인지 궁금합니다.
gcc 소스를 확인하고 싶지만 그 방대한 소스에서 정확히 어디를 봐야할지 감을 못잡겠습니다. 혹시 linux에서 로칼 변수를 위한 스택 할당 규칙이나 혹은 이에 대한 룰을 gcc 소스서 확인하는 방법을 아시는 분 계시면 조언 부탁드립니다.

버려진의 이미지

음... 설명하려면 길고 인터넷 찾아보시면 관련 문서를 얻으실 수 있을테니 간단히...

우선 저 배열에 16만큼 할당됩니다. 이건 컴파일 옵션으로 조절이 가능합니다. 그러니 넘어가고...

스택에는 저것 외에도 esp ebp도 push되어 있습니다. 각각 4씩..

16+4+4면 24네요.

그런데 효율을 위해 컴파일러는 16씩 정렬을 맞추려고 합니다.

그래서 배열 다음에는 dummy가 8붙어야 합니다. (총합 16을 맞출수는 없고 32를 맞춰야 하니까)

그래서 16+8=24가 함수 내부에서 할당된 것이죠.

성능에 대한 문제 + 오버플로우에 대한 대비 등이 짬뽕된 이유인 것으로 알고 있습니다.

choco6의 이미지

답변 감사드립니다.
그런데 제가 잘못 알고 있는게 있었나요. 제가 알기론 esp는 스택에 저장되지 않는걸로 아는데... ebp는 calling function의 stack frame의 주소이므로 called function에서 당연히 스택에 push되어야 하겠지만요. 그리고 그것을 차치하더라도 24바이트에는 ebp나 esp가 push되는 공간은 아니지요. 이미 <func> 라인에서 push %ebp 가 실행되었으므로 <func+3>에서 sub $0x18, %esp는 순수하게 local variables를 위한 공간이 아닌가요?

그리고 16씩 정렬이 된다면 buf1[2]나 buf1[4]는 왜 4바이트가 할당되는지는 설명이 되지 않습니다. buf[7]까지는 16씩 할당이 되면서 buf[8]에 와서는 다시 8이 할당이 되는건 word size단위에서는 4씩 정렬을 하면서 word size가 아닌 값에 대해서는 16씩 정렬을 하는 셈이 되는건가요?

버려진의 이미지

제가 잘못 이야기 했네요. esp가 아니라 리턴 어드레스가 들어갑니다. 크기는 똑같으니 패스 ;; (참고로 그 뒤에는 함수의 argument? 들이 들어갑니다. 아키텍쳐에 따라 차이가 있기는 하지만)

음 그건 그렇고 실제로 크기를 1씩 늘리면서 실험을 해보면 크기가 들쑥날쑥 할때가 있더라구요. 정확한 이유는 모르겠지만... [2]나 [4]가 그런 경우에 해당하는 것 같습니다. 아마 [16]이상으로 커지면 규칙성 있는 모습을 보일 겁니다. 문서에서는 그렇게 봤는데 직접 실험해 본적은 없네요. :)

아무튼 자세한건 내일 다시 보도록 하겠습니다. 그 사이 고수님이 답변을 주실지도 모르겠네요. 전 지금 윈도거든요. 디아블로1이 갑자기 하고 싶어져서.. 그런데 시디 인식 에러가 자꾸 나는거 있죠. ^^;

choco6의 이미지

네.. 그렇군요.
그러나 확실한건 24바이트에는 calling function의 리턴주소와 ebp가 저장되는 공간이 아닙니다. 그것은 이미 <func+3> 라인 이전에 모두 스택에 저장되어 있으니까요. 리턴 어드레스와 ebp까지 합치면 총 32바이트 공간이 할당되는 셈입니다. gcc 소스에서 확인하는게 가장 확실한 방법같은데 그거참 어느 부분에 쳐박혀있는지 확인할 수가 없으니... --;;;

음... 그런데 저도 갑자기 스타크래프트가 하고 싶어지는군요. ^^;

버려진의 이미지

네 24바이트 안에 저장되는건 아닙니다.

간단히

버퍼(16) + 더미(8 ) + ebp(4) + ret(4)

이런식으로..

ebp와 ret을 언급하지 않으면 더미가 왜 8이 붙어야 하는지 설명할 길이 없어서요.

내일은 윈도98을 설치해봐야겠습니다. 좀처럼 안되네요. ^^;

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.