[완료]스택의 구조에 대해 질문드립니다.

0mbres의 이미지

한 함수가 호출될 때 만들어진 스택 프레임에 그 함수의 인자나 지역변수, 그리고 스택 프레임 포인터(SFP)리턴 주소(RET)가 포함된다고 알고 있습니다.
SFP의 경우 함수가 호출되거나 반환될 때 ESP, EBP 레지스터의 값을 조정하기 위해 필요한 것으로 원리를 이해하고 있는데, 리턴 주소는 어떤 목적으로 필요한 것인지 헷갈립니다. 텍스트 세그먼트에 있는 호출 코드로 돌아가기 위한 것이 맞나요?

Segment fault가 일어나는 원리에 대해서도 질문드립니다.
스택 프레임의 구조가 아래와 같을 때

(↓스택이 쌓이는 방향)
버퍼
SFP
RET

예를 들어 버퍼에 용량 이상의 값을 복사하려 하면 스택의 RET 값이 오염돼서 프로그램이 정상적으로 종료하지 못한다고 알고 있습니다. 그런데 스택이 쌓여가는 구조상, 반대 방향으로 초과된 값들이 쌓여야 하는 게 아닌가요?

XXX
XXX
버퍼
SFP
RET

↑초과된 값들이 이런 구조가 아닌

버퍼
XXX
XXX

↑이런 구조가 되는 원리를 알고 싶습니다.

drinkme의 이미지

뒤집으세요.

RET
SFP
버퍼
..
..

push하게 되면, sp는 감소합니다.

ipes4579의 이미지

스택 호출 시 EIP값이 저장되어, RET 할 때 저장된 EIP가 호출되어 다음 명령으로 가게 됩니다.

그리고 메모리맵을 보시면 알게 될텐데, 스택은 메모리에서 뒤부터 올라옵니다 ^^ return address도 뒤쪽에 저장됩니다. 텍스트 저장은 앞에서부터 하구요.

0mbres의 이미지

제가 처음부터 이해를 잘못한 건지 스택을 잘못 그려서 질문을 잘못 드린 건지 모르겠네요.

(낮은 주소)

[text]
[data]
[bss ]
[heap]

버퍼
SFP
RET
[stack]

(높은 주소)

이런 구조라면, RET, SFP, 버퍼 순서로 스택에 쌓여가는 게 아닌가요?
그래서 만약 초과된 데이터를 스택에 반입하더라도 RET, SFP, 버퍼, XXXXXX 이렇게 낮은 주소 방향으로 쌓여야 하는 게 아닌가 질문드린 겁니다.

질문과 별개로 참고 도서 추천 좀 부탁드립니다. ㅠㅠ 제가 보는 책에서는 RET에 대해서도 언급이 안 돼 있네요.

pastime의 이미지

아시다시피 스택에 버퍼를 할당(선언)하면
버퍼의 시작 주소는 스택의 가장 낮은 주소를 가리킵니다.
여기에 strcpy나 memcpy 등으로 버퍼 크기보다 큰 데이터를 복사하면
버퍼 위에 있는 지역 변수나 SFP, RET 등이 깨지는 것입니다.

말씀하신 초과된 데이터를 스택에 반입한다는 의미는
스택에 데이터를 계속 할당하는 것이 아니라
위와 같은 함수 등으로 메모리의 내용을 복사하는 것을 뜻하는 것 같습니다.

0mbres의 이미지

만약 2바이트 크기의 버퍼가 할당되어서

(낮은 주소)

1바이트 버퍼
1바이트 버퍼
SFP
RET

(높은 주소)

이곳에 1바이트 문자를 strcpy를 이용해 계속해서 복사하면

(낮은 주소)

1바이트 버퍼
[첫번째 할당된 문자]
SFP
RET

(높은 주소)

(낮은 주소)

[두번째 할당된 문자]
[첫번째 할당된 문자]
SFP
RET

(높은 주소)

이렇게 되고, 버퍼를 초과한 3번째로 문자를 할당하려 할 때는

(낮은 주소)

[세번째 할당된 문자] -> 버퍼 용량을 초과함
[두번째 할당된 문자]
[첫번째 할당된 문자]
SFP
RET

(높은 주소)

↑이렇게 되는 게 아니라

(낮은 주소)

[첫번째 할당된 문자]
1바이트 버퍼
SFP
RET

(높은 주소)

(낮은 주소)

[첫번째 할당된 문자]
[두번째 할당된 문자]
SFP
RET

(높은 주소)

(낮은 주소)

[첫번째 할당된 문자]
[두번째 할당된 문자]
[세번째 할당된 문자]
RET

(높은 주소)

이렇게 된다는 말씀인가요?
저는 스택이라면 무조건 높은 주소에서 낮은 주소 방향으로
데이터가 쌓여가는 줄 알았습니다. 버퍼를 할당한 후에는 그 버퍼 안에서 반대 방향(낮은 주소에서 높은주소로)으로 데이터가 할당된다고 이해해도 될까요?

pastime의 이미지

그렇게 이해하셔도 될 것 같습니다.

스택이 특별한 것은 지역 변수 (버퍼) 영역을 할당할 때이고
strcpy나 memcpy 등은 스택이건 힙이건 구분하지 않고
항상 낮은 주소에서 높은 주소 순으로 동작합니다.

0mbres의 이미지

고맙습니다. 이제야 이해했습니다.
스택 문제로 계속 헷갈리다보니 데이터가 저장되는 순서까지도 혼란스러워했네요.
답변해주신 분들 모두 고맙습니다!

댓글 달기

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