[C/C++]Local Variable을 Return 할 때...

akcytm의 이미지

int* out()
{
int a=5;
return &a;
}
위와 같은 함수를 정의하고

main()에서
int* num=out();의 코드를 실행했습니다.
Local Variable을 Return했으니, 전 곧바로 값이 깨질것이라 생각했지만
실행결과를 해석하기 어려웠습니다.

1.
int* num=out();의 실행이 끝나고
(*num)++;을 수행했더니 6이라는 값이 나왔습니다.
값이 아직 안깨졌습니다.
loop와 같은 다른 명령을 수행해도 값은 안깨집니다.

2.
int* num=out();의 실행이 끝나고
cout<<*z< *z의 값이 깨졌습니다.

3.
int* num=out();의 실행이 끝나고
cout<<123< *z의 값이 깨졌습니다.

z의 값이 깨지는 시점이 어디일까요? 디버깅을 할려고 했더니,
내부 라이브러리로 jmp되어서 ㅈㅈ쳤습니다. 왜 하필 cout이 실행된 다음에
값이 깨질까요;;

akcytm의 이미지

2.
int* num=out();의 실행이 끝나고
cout<<*z< *z의 값이 깨졌습니다.

3.
int* num=out();의 실행이 끝나고
cout<<123< *z의 값이 깨졌습니다.

실행결과가 무척 흥미롭네요. 여러가지 테스트를 해봤는데, cout이 실행된 다음에만
*z의 값이 깨지는 것 같습니다. 왜 이런것이며, *z의 값이 깨지는 시점은 언제일까요?

akcytm의 이미지

2.
int* num=out();의 실행이 끝나고 cout<<*z;을 실행했더니 *z의 값이 깨졌습니다.

3.
int* num=out();의 실행이 끝나고 cout<<123;와 같이 z와 전혀 관계없는 값을 출력해도
*z의 값이 깨졌습니다.

실행결과가 무척 흥미롭네요. 여러가지 테스트를 해봤는데, cout이 실행된 다음에만
*z의 값이 깨지는 것 같습니다. 왜 이런것이며, *z의 값이 깨지는 시점은 언제일까요?

kukyakya의 이미지

스택 포인터를 넘는 곳은 언제 깨질 지 알 수 없습니다. 아래 부분에 지역변수를 사용하는 함수 호출이 반복되는 경우 값이 깨지는 것을 확인하실 수 있을 것 같습니다. 물론 최적화 레벨에 따라 지역변수를 스택에 할당하지 않는 경우라면 값이 꺠지지 않겠지만요.

HDNua의 이미지

#include <stdio.h>
 
void *func();
void empty();
 
int main(void)
{
    int *p;
 
    p = func();
    printf("*p: %d\n", *p);
 
    empty();
    printf("*p: %d\n", *p);
 
    return 0;
}
 
void *func()
{
    int var = 10;
    return &var;
}
void empty()
{
 
}
 
// 결과
// *p: 10
// *p: 쓰레기값

Visual Studio 2010으로 빌드하고 실행하였을 때의 결과입니다.
지역 변수를 할당하지 않는 empty() 함수가 호출되었음에도 *p의 값이 변한 것으로 봐선
함수 호출 자체도 스택에 들어가는 모양입니다.
아니면 이건 컴파일러마다 결과가 다를까요..

저는 이렇게 생각했습니다.

klyx의 이미지

당연히 결과는 컴파일러에 따라서 다를 수 있습니다. 같은 컴파일러에서도 매번 결과가 같다는 보장은 못합니다.
함수 호출이 스택을 이용하는건 맞지만, 이게 함수 호출이 스택을 이용하는 증거가 되진 못합니다.

klyx의 이미지

표준에서 정의되지 않은 동작은 말그대로 정의되지 않았기 때문에 알수 없는것입니다.
'바로 깨질것이다'라고 조차도 정의할수 없는것입니다. 어느시점부터 쓸수 없게 될지도 정의되지 않습니다.
정의되지 않은 동작에 '이유'를 찾으려고 하는건 컴파일러 그자체를 구현하려는게 아니라면 아무런 의미가 없습니다.

댓글 달기

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