인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

cafe0406님의 프로필 이미지

작성한 질문수

독하게 시작하는 C 프로그래밍

가변 길이 입력에 의한 Stack frame 손상

Stack Frame과 메모리 질문

해결된 질문

작성

·

76

0

안녕하세요?
강의에서는 메모리 상에서 szBuffer와 nData가 바로 인접해서 서로에게 영향을 주는 상황이 나온 것으로 이해했습니다.

그런데 제가 변수가 메모리에 어떻게 저장되는지 궁금하여 이전에 간단히

#include <stdio.h>

int main(void)

{

int x = 16;

int y = 8;

int z = 4;

return 0;

}

로 두고 메모리를 따라가 봤더니 다음과 같은 결과가 나왔습니다.

0x000000886A2FFB04 10 00 00 00 ....

0x000000886A2FFB08 b4 05 63 2e ?.c.

0x000000886A2FFB0C fc 7f 00 00 ?...

0x000000886A2FFB10 c8 d2 29 d8 ??)?

0x000000886A2FFB14 bc d9 00 00 ??..

0x000000886A2FFB18 02 00 00 00 ....

0x000000886A2FFB1C 00 00 00 00 ....

0x000000886A2FFB20 00 00 00 00 ....

0x000000886A2FFB24 08 00 00 00 ....

0x000000886A2FFB28 16 20 60 2e . `.

0x000000886A2FFB2C fc 7f 00 00 ?...

0x000000886A2FFB30 00 00 00 00 ....

0x000000886A2FFB34 88 00 00 00 ?...

0x000000886A2FFB38 00 00 00 00 ....

0x000000886A2FFB3C 00 00 00 00 ....

0x000000886A2FFB40 00 82 68 b3 .?h?

0x000000886A2FFB44 04 00 00 00 ....(

(볼드체 + 기울임이 각각 x, y, z입니다)
여기서 질문이 두 가지 있습니다.

  1. 보안 설정에서 아무것도 바꾸지 않았는데 변수들이 모두 메모리 주소를 32씩 띄워서 저장되고 있습니다. int는 4byte이니 원칙적으로는 메모리 주소를 4씩만 띄워서 저장해도 될 것 같은데 (강의상에서도 szBuffer와 nData가 붙어서 저장된 것처럼) 왜 이런 것일까요?

  2. 변수 x, y, z는 자동변수이므로 현재 저장된 메모리 공간은stack frame으로 이해했습니다. 강의에서 stack frame의 위쪽 공간일수록 메모리의 0번지에 가까워진다고 하셨는데 왜 x - > y -> z로 갈수록 메모리 주소가 증가하는 걸까요? 가장 먼저 정의된 변수 x가 stack의 가장 밑에 저장되고 그 위에 y, z가 정의되었다고 한다면 z로 갈수록 메모리 주소가 0번지에 가까워져야 하지 않을까... 생각을 하였습니다.

감사합니다.

답변 2

0

널널한 개발자님의 프로필 이미지
널널한 개발자
지식공유자

  1. 빌드 모드(Release, Debug, 혹은 사용자 정의)에 따라 달라질 수 있습니다. 보여준 예시로 봤을 때는 Debug 모드로 추정됩니다. 이 경우 스택 프레임 손상을 감지하기 위한 코드가 추가되며 그 과정에서 메모리가 더 사용됩니다. Release 모드 빌드 후 다시 확인해보시면 충분히 비교가 될 것입니다. 단 이 때, 반드시 컴파일러 최적화 옵션을 꺼야 실제로 메모리가 사용되도록 컴파일 됩니다.

  2. 이는 전적으로 컴파일러 선택입니다. 눈에 보이는 코드 순서그대로 스택에 쌓여 올라가는 것이 아닐 수 있습니다. 즉 먼저 선언된 x가 스택프레임 바닥쪽에 자리하는 것이 아니라 코드 상 눈에 보이는 순서 그대로 스택에서 메모리 위치가 잡히도록 컴파일 된다면 순서가 바뀌지 않습니다.

참고하시기 바랍니다. 😄

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다. cafe0406님.

스택 프레임과 메모리에 대한 이해를 돕기 위한 질문이군요. C 프로그래밍에서 메모리 관리와 스택 프레임 이해는 아주 중요한 주제입니다. 질문해 주신 두 가지 부분에 대해 답변드리겠습니다.

1. 변수가 메모리에 32씩 띄워서 저장되는 이유

변수가 메모리에 어떻게 배치되는지는 여러 요인에 따라 달라질 수 있습니다. 이러한 요인들은 컴파일러에 따라 다를 수 있는데, 보통 다음과 같은 이유로 메모리 공간이 더 여유 있게 할당됩니다:

  • 메모리 정렬과 패딩: 보통 컴파일러는 메모리 접근 속도를 최적화하기 위해 정렬을 사용합니다. 이는 특정 크기의 변수들이 메모리 주소의 특정 배수에 놓여야 하도록 강제함으로써 발생할 수 있습니다. 이로 인해 ‘패딩’이라는 추가 공간이 생길 수 있습니다. 이는 성능을 최적화하고, 특정 하드웨어에서의 안정성을 보장하기 위한 일반적인 기법입니다.

강의에서의 szBuffernData가 붙어서 저장된 것은 아마도 디버깅 환경이나 컴파일러 최적화 수준에 따른 차이일 수 있습니다.

2. 스택 프레임 내 메모리 주소 증가

C의 스택에서 메모리는 높은 주소에서 낮은 주소로 할당됩니다. 즉, 스택의 맨 위는 가장 높은 메모리 주소에 해당하고, 아래로 내려갈수록 더 낮은 주소를 가리키게 됩니다.

하지만 C 코드에서 변수가 스택에 할당되는 순서는 코드 최적화나 변수 사용 패턴에 따라 달라질 수 있습니다. 변수들이 실행되는 순서와 무관하게 컴파일러는 최적화나 특정 규칙에 따라 변수를 스택에 놓을 수 있는 것이죠. 가령, 위 코드에서는 x, y, z가 메모리 상에서 증가하는 주소로 배치된 것처럼 보이지만, 이는 컴파일러가 생성한 최적화 결과일 수 있습니다.

이는 스택 메모리 구조와 매핑하여 직접적으로 0번지가 아니라, 프로그램의 스택 영역에서 상대적 위치가 중요한 것입니다. 따라서, 코드 내에서 메모리 주소나 배치를 컴파일러의 최적화나 설정하에 달리 이해해야 합니다.

이 주제에 대해 추가적으로 관심이 있으시다면 아래와 같은 관련 질문들을 참고하시면 좋을 것 같습니다:

  1. 스택 쓰레기 값? 관련 질문 드립니다.

    • 스택 메모리와 변수들이 메모리에 저장되는 방식에 대해 다뤄진 게시물로, 쓰레기 값과 디버깅 모드에서의 메모리 초기화에 대한 설명이 있습니다.
  2. 정수형태 변수 메모리상 확인방법 및 단순 대입 관련 문의

    • 정수형 변수의 메모리 상 확인 방법과 대입 연산의 의미에 관한 설명으로, 메모리의 동작 방식을 자세히 이해하는 데 도움을 줄 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

cafe0406님의 프로필 이미지

작성한 질문수

질문하기