로컬 변수의 주소 리턴

wakeup의 이미지

몇일 전 회사 면접보는 데 간단한 필기 테스트를 했습니다.
몇줄의 코드를 주고 잘못된 부분을 설명하라는 테스트였습니다.
코드가 잘못되었다고 생각이 드는데, 집에와서 해보니 정상적으로 동작이 되더라고요,
제가 잘못알고 있는건지..
코드는 아래와 같습니다.

int *sum(int a, int b)
{
  int c = a + b;
  return &c;
}
 
int main()
{
  int r = *sum(1,2);
  printf("%d\n",r);
  return 0;
}

전 쓰레기 값이 나올줄 알았는데, 3이 출력되더군요..
제가 잘못알고 있는건가요?

plustag의 이미지

쓰레기가 안나온건 운이 좋아서 그런거 같은데요..
스택에 다른 내용이 들어가면 쓰레기가 들어갈거 같습니다만..

누구냐 넌?

jick의 이미지

해석: 자기가 짤 때 잘 돌아갑니다.
팀장이 볼 때 잘 돌아갑니다.
전체회의때도 잘 돌아갑니다.
QA가 해볼 때도 잘 돌아갑니다.
고객 사이트에 들어갑니다.
드디어! 쓰레기값이 나옵니다.
전체 시스템이 안 돌아갑니다.
전 팀원이 사흘간 밤샙니다.
원인이 밝혀집니다.
짤립니다.
바이바이~~~~~

* 버전관리 툴을 사용하지 않는 막장회사의 경우 누가 했는지 밝혀내지 못해서 안 짤릴 수도 있습니다. -.-

grassman의 이미지

architecture에 따라서 다른 결과를 얻을 수도 있습니다. x86의 경우에는 해당 함수가 thread로 돌아가지
않으며 컴파일러 최적화를 하지 않고 반환 받은 포인터 참조가 다른 함수 호출 이전까지만 수행된다는 가정하에서 유효한 값을 얻을 수 있습니다. (현존하는 x86용 컴파일러가 stack 영역을 다루는 방법이 동일하게 되어 있어서 그렇습니다)

결론은 항상 '절대 사용하면 안되는 코드'라는 것입니다.

cppig1995의 이미지

int *c = sum(1, 2);
printptrval(c); // void printptrval(int *ptr) { printf("%d", *ptr); }

마치 저건 대형 클래스를 const ... &로 주고받으면 수행이 빨라진다고 해서
const BigClass &operator*(const BigClass &rhs) { return BigClass(this->test * rhs.test); }
하는 꼴이로군요.
--
임수서룬뫼 윤희수 {cppig1995/돼지군}

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

mg2000의 이미지

실제 피를 본건 아니고... ^^;;;;;

윈도우에서 그렇게 된다고 유닉스에서 소스 그대로 가지고 가서 돌렸다가...

3일간 디버깅... ㅡ.ㅡ;;;;;

결국 지역변수 주소를 리턴한게 화근이었습니다.

cats96의 이미지

위와 같이 간단한 소스에서는 금방 찾겠지만.( 위의 경험이 없다면 헤멜수도 ^^)
방대한 소스에서는 미칩니다.
지역변수의 주소를 리턴하는 실수는 조심하세요

powerson의 이미지


cats96님 말씀에 절대 공감입니다. 간단한 소스야 바로 눈으로도 확인가능하고, debugger로 돌려도 바로 찾을 수 있지만, 소스의 양이 몇천에서 몇만으로 가게 되면, 이건 SIGSEGV도 아니라서 어디서 어떻게 바뀌는지 더더욱 찾기 힘들죠..

------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.

------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.

whitenoise의 이미지

int c를 static으로 선언하면 어떻게 될까요?

seoleda의 이미지

singletone을 구현할때 지역변수를 static으로 선언해서 리턴하는 경우를 볼수 있습니다.

따라서, static를 붙이면 전역변수와 동일한 영역에 생성하기 때문에,

리턴해도 유효한 번지라고 할 수 있습니다.

다만, 여러군데에서 그 번지를 수정하는 경우에 버그가 발생하면,

전역변수를 사용하는 경우만큼 찾기가 어려울것 같습니다.

김일영의 이미지

X Window System 프로그램에서 저런 코드를 본 적이 있는데,
메모리 에러가 나는 것이 아니라 XtCreateShell need not NULL parent 인지 뭐 그런 에러가 나더군요.
어디서 저런 코드를 쓰느냐에 따라서 이렇게 황당한 경우도 있으니
절대 저렇게 사용하지 않는게 최선이겠죠.
저런 코드 적발시 작성자를 응징~

codepage의 이미지

뭐 플랫폼에 따라서 저런 소스코드 하나 때문에 전체 프로그램이 다운되는 경우가 있습니다.

madman93의 이미지

return_local_val.c 파일을 만들고 컴파일 해 보았습니다.

gcc -g -o return_local_val return_local_val.c
return_local_val.c: In function 'sum':
return_local_val.c:6: warning: function returns address of local variable

결과값은 3이라고 나오기는 하지만

gcc에서의 warning을 무시하면 안되겠군요
---------------------------------------------
리눅스가 싫다 우분투가 좋다
---------------------------------------------

---------------------------------------------
git init
git add .
git commit -am "project init"
---------------------------------------------

토끼아빠의 이미지

오늘도 많이 배웠습니다...

좋은 하루 되세요!!

좋은 하루 되세요!!

cats96의 이미지

madman93님 GCC 버전 몇인가요?
GCC에서 저런것도 워닝으로 잡아주다니 좋네요 ㅋㅋ
근데 전 워닝은 잘 패스하는 스탈이라...
워닝도 눈여겨 봐야겠네요

madman93의 이미지

madman93@madman93-desktop:~$ gcc --version
gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

다른 버전에서는 안 보일수 있나 보군요!!!!
---------------------------------------------
svn + trac + my project --> success ???
---------------------------------------------

---------------------------------------------
git init
git add .
git commit -am "project init"
---------------------------------------------

댓글 달기

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