C언어 스택 구현 중... 힙과 데이터 메모리에 관련한 질문이 생겼습니다.
C언어로 스택을 구현하고 있습니다.
스택 푸쉬, 팝 등등은 잘 됩니다. 근데 이걸 main함수 밖에다가 따로, 스택에 있는 데이터를 print하는 함수를 만들어서 출력을 하려고 보니 문제가 생겼습니다.
아래는 제 코드입니다.
#include <stdio.h> #include <stdbool.h> #define MAX_SIZE 100 typedef struct { int key; int data; } element; typedef struct { element* item; int top; } Stack; void CreateStack(Stack* sp) { element ele[MAX_SIZE]; sp->item = ele; sp->top = -1; } bool Push(Stack* sp, element ele) { if (sp->top == 100) { printf("error : stack is full"); return false; } else { sp->top++; sp->item[sp->top].data = ele.data; sp->item[sp->top].key = ele.key; return true; } } element Pop(Stack* sp) { if (sp->top == -1) { printf("error : stack is empty\n"); } else { element temp; temp = sp->item[sp->top]; sp->top--; return temp; } } bool IsFull(Stack* sp) { if (sp->top == 100) { printf("Stack is full\n"); return true; } else { printf("Stack is not full\n"); return false; } } bool IsEmpty(Stack* sp) { if (sp->top == -1) { printf("Stack is empty\n"); return true; } else { printf("Stack is not empty\n"); return false; } } void PrintStack(Stack* sp) { for (int i = 0; i < sp->top; i++) { printf("%d %d\n", sp->item[i].key, sp->item[i].data); } } int main() { element el1; el1.data = 10; el1.key = 1; element el2; el2.data = 20; el2.key = 2; element el3; el3.data = 30; el3.key = 3; element el4; el4.data = 40; el4.key = 4; Stack st1; Stack* stp; stp = &st1; CreateStack(stp); Push(stp, el1); Push(stp, el2); Push(stp, el3); Push(stp, el4); Push(stp, el1); Push(stp, el2); element tmp1 = Pop(stp); for (int i = 0; i < stp->top; i++) { printf("%d %d\n", stp->item[i].key, stp->item[i].data); } PrintStack(stp); IsFull(stp); IsEmpty(stp); }
여기서 이상한 점이...
main함수 안에서 스택을 출력하는 건 잘 됩니다. 순서대로 1 10, 2 20, 3 30, 4 40 이렇게 잘 나옵니다.
근데 그 아래 따로 함수로 선언한 PrintStack으로 출력을 하면
1 10 2832919 2938281 2948382 2938374
이런식으로 처음 값만 제대로 나오고 그 뒤로부터는 포인터 값? 으로 추정되는 이상한 값들이 나옵니다.
생각을 해 봤는데
1. 혹시 PrintStack함수에 인자로 들어가는 Stack* 의 element 어레이가 사라진 건가.. 싶기도 하고 아니면
2. 애초에 CreateStack에서, element 어레이를 생성하고, element의 포인터를 리턴을 해 줘도 그 함수를 빠져 나오면 함수 안에서 생성된 element 어레이는 다시 사라져서 결국 이상한 곳을 가리키게 된 것인가 싶기도 합니다..
element ele[MAX_SIZE]를 CreateStack 밖에다가 그냥 전역변수로 선언하면 또 PrintStack은 문제없이 실행 됩니다.
2 가 문제라면 PrintStack 말고 다른 모든 함수나 main문 안의 Printf문에서도 오류가 생겨야 할 것 같은데 그러지는 않고...
처음 탐색하는 값만 제대로 나오고 그 후부터는 이상한 포인터값이 나오는 것도 이상하고...(맨 처음에 출력을 2번쨰 데이터로 하면 2번째 데이터는 잘 나옵니다. 근데 또 그 후 부터 이상하게 나옵니다.
구현이 되긴 하지만.. 좀 더 정확히 공부하고 싶어서 이렇게 질문 올립니다.
감사합니다.
코드를 이렇게 밖에 못올리겠습니다.. 어떻게 하나요...
매우 보기 나쁘네요 .. ㅜ
글 올릴 때 보시면.. 코드는 <code>~<
글 올릴 때 보시면.. 코드는 <code>~</code> 블럭으로 감싸라고 알려 드리고 있는데요.
감사합니다.
근데 자동으로 된건가... 제가 안했는데 이쁘게 처리되었네요
코드 실행 결과입니다.
1 10
2 20
3 30
4 40
1 10
1395198872 3930052
3930104 3930112
3930096 3930108
문제의 원인은 (높은 확률로) 2번이 맞습니다.
문제의 원인은 (높은 확률로) 2번이 맞습니다.
CreateStack 함수가 종료되면서 지역 변수인 ele 는 더 이상 유효하지 않게 되고, 다른 함수가 호출되면서 스택프레임이 덮어쓰여서 값이 바뀌었겠죠.
처음에 잘 나온 것은, 그저 운이 좋았을 뿐입니다. 덮어쓰이지 않은 상태에서 읽으면 원래 썼던 값이 나오겠죠.
지금 코드의 경우 ele 배열의 원소의 개수가 100개이고 그래서 800바이트 정도를 차지하는데, 다른 함수가 호출될 때 스택 프레임은 높은 주소에서부터 쌓이다보니 가장 낮은 주소에 있는 ele[0]까지는 미처 덮어쓰지 못하고 끝났던 거죠.
제가 지금 리눅스의 gcc로 컴파일하고 실행했을 때는 PrintStack 함수마저도 올바른 결과를 냈습니다. 하지만
덮어쓰인 결과가 나오죠.
좋은 하루 되세요!
참고해보세요.
함수 안에 지역 변수. 사용 문제점
함수를 나가면. 배열 데이터'가 사라지거나. 남더라도. 변경 된다고 알고 있습니다.
https://ideone.com/FtxpXu
씹어먹는 C 언어 - <17. 변수의 생존 조건 및 데이터 세그먼트의 구조
http://itguru.tistory.com/83
윈도우10 64비트에서 해보니. 잘못된 값이 출력 됩니다.
운이 좋은건지. 확인이 안된건지. 잘못된 메모리 접근 메시지는 보이지 않네요.
해당 주소'는 제대로 얻어서. 접근 및 변경은 가능한가 봅니다.
동적 메모리 할당을 하거나. 전역 변수 설정. static 변수를 만드는 방법. 등에 해결방법이 있습니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기