함수내 지역변수 리턴에 관함.

coathanger의 이미지

여러분들 즐거운 주말 보내시고 계신가요..

어쩌면 이 질문이 현 그룹에서 자주 언급된 내용일 수 있습니다. 하지만 개인적으로 이해를 하지 못하여
아래 이어서.. 염치불구하고 다시 포스팅합니다.

일단 아래 내용이 좀 길지만.. 보아 주십시오.

/*
* 아래 함수에서 배열을 리턴하려고 합니다.
* 함수내 지역변수를 리턴을 할 경우 스택에 저장되는 변수라 getStrArr함수의 scope를 벗어나면
* 바로 소멸되는 성격을 가지고 있다는 것을 관련 포스트에서 보았습니다.
*/
char* getStrArr(void)
{
char temp[5];
...
return temp;
}

[일단 문제 해결을 정리 해 보았습니다.]
1. 전역변수를 선언하여 프로그램 종료시 까지 메모리를 유지한다.(지양)
2. static을 선언하여 프로그램 끝날 때 까지 해당 배열 변수의 메모리를 유지한다.(지양)
- static char temp[5]
3. malloc() 즉, heap 영역에 메모리를 할당하여, 사용자가 메모리 해제 시점을 지정한다.(반드시 해제해야 함)
4. 호출 쪽에서 인자로 배열을 전달하고 그 배열을 리턴한다.(지향)

[질문 1] 이 문제가 배열문제에만 국한 된 것인지 궁금합니다.
예를 들어 아래와 같이 배열이 아닌 정수값을 넘길 때도 이러한 메모리 문제가 발생하는 건가요?

[생각] 배열에만 현 문제가 야기된다면 제가 생각할 수 있는 것은.. 배열의 주소를 넘김으로 인해 함수를 빠져
나오고 나서 해당 주소를 저장한 다른 변수에서 그 주소에 있는 값을 참조하려고 할때 이미 메모리가
해제되어 의도하는 값을 얻어 올 수 없다는 것이 맞는가요..
call by value에 의한 아래와 같은 하나의 값만을 리턴할 경우는 함수 메모리 해제 시점이 값 복사
이후라서 아래 함수는 올바른 경우인가요?

int getNumber()
{
int sum, a = 1, b = 2;

sum = a + b;

return sum;
}

[질문 2] malloc()로 할당된 메모리 값을 해제하기 위해 호출 쪽에서 그 주소를 받은 동일한 주소를 가리키는
tempData를 free()해 주는 것이 맞나요?(아래 예제 소스 참조)

Byte* GetPacketLength(Byte* anyData)
{
Byte* retData = (Byte*) malloc(sizeof(Byte) * 2);

... 인자로 받은 anyData에 대해 처리....

rgucCnt[0] = 10; /* 만약 처리 값이 10, 20 라고 가정 */
rgucCnt[1] = 20;

return retData;
}
int main(void)
{
Byte* tempData ;
Byte recvData[2];

tempData = GetPacketLength(sendData);

recvData[0] = tempData[0];
recvData[1] = tempData[1];

free(tempData);
}
[질문3] 4. 호출 쪽에서 인자로 배열을 전달하고 그 배열을 리턴한다.(지향) , 이 방법의 예를 들어 주실 수 없을까요..
질문이 깁니다... 나름대로 성의 것 작성하려 노력하였습니다. :-)

ktd2004의 이미지

>> [질문 1] 이 문제가 배열문제에만 국한 된 것인지 궁금합니다.
예 맞습니다.
정확하게는 value가 아닌 reference의 경우(포인터 혹은 배열)에만 해당하는 것이겠죠.

>> [질문 2] malloc()로 할당된 메모리 값을 해제하기 위해 호출 쪽에서 그 주소를 받은 동일한 주소를 가리키는
>> tempData를 free()해 주는 것이 맞나요?(아래 예제 소스 참조)
예 맞습니다.
하지만 이 함수를 호출하는 쪽에서 항상 반환된 메모리를 해제해야만한다는 제약이 따르므로
문제가 발생할 소지(메모리를 해제하는 것을 잊는 경우)가 있습니다.

>> [질문3] 4. 호출 쪽에서 인자로 배열을 전달하고 그 배열을 리턴한다.(지향)
>> , 이 방법의 예를 들어 주실 수 없을까요..
그냥 간단히 문자열 관련 함수들의 대부분이 그런식으로 동작합니다.

/* 대략 다음과 같은 방식이겠죠 */
char obuf1[100];
char obuf2[100];
char *ibuf = "This is example.";
 
strcpy( obut1, strcpy( obuf2, ibuf);

제 답변에 잘못된 내용이 있으면 지적해 주십시오..
다른 분께서 더 자세한 답변 달아주실 것 같습니다. ^^;

Necromancer의 이미지

strcpy() 인자로 넘어가는 obuf1, obuf2, ibuf 등은 배열 자체가 아니라 해당 배열에 대한 포인터가 됩니다.

질문 3번은 저도 어떻게 구현하는지는 잘 모르겠네요.
(현업에서도 쓰는거 못봤습니다. 배열을 인수로 넘기는 것은
스택 복사과정에서 overhead 때문에 잘 안쓰는 걸로 알고 있고요)

Written By the Black Knight of Destruction

Written By the Black Knight of Destruction

ktd2004의 이미지

저는 배열을 전달한다는 것을 배열의 포인터를 전달한다고 이해를 했는데
제가 잘못 이해한 것 같습니다.

배열을 전달하는 방식은 다음과 같은 방식이 안닐까요?
구조체 내에 배열을 넣고 해당 구조체를 call by value로 전달하는 방법

typedef struct mystruct{
    char buf1[256];
    char buf2[256];
}MyStruct;
 
MyStruct func( MyStruct ms)
{
    MyStruct ms1;
    strcpy( ms1.buf1, ms.buf1);
    strcpy( ms1.buf2, ms.buf2);
 
    return ms1;
}

항상 하는 말이지만,
잘못된 내용이 있으면 지적 부탁드립니다. ^^;

Necromancer의 이미지

질문 1 - scope 벗어나면 지역변수는 소멸되는거 맞습니다.

따라서 malloc()을 해서 넘기던가, 호출하는 쪽에서 공간을 확보해줘야 합니다.

그리고 static으로 선언된 변수는 프로그램 전체에서 단 하나만이 생깁니다.
함수 호출시에 생성되는 것이 아니라 미리 생성되고요. 따라서 특정 함수 내에서만
사용가능한 '전역변수' 로 보셔야 합니다.

여러 군데에서 임시 저장용으로
static으로 하면 지역변수 소멸 문제는 해결되지만 이런점 고려 안하고 만든다면
원인모를 오류를 내는 원인이 될 수 있으니 조심하셔야 합니다.
(멀티스레드 쪽으로 가게 되면 굉장히 심각해집니다)

질문 2 - malloc()으로 받은 주소 그대로 돌려주면 됩니다.

malloc()과 free()은 할당된 메모리 블럭의 앞뒤에 블럭 정보를 다 표시해서 관리합니다.
관리 방식은 malloc(), free() 구현된 라이브러리 나름이고요.

다만 엉뚱한 주소를 리턴하면 프로그램 뻗습니다.

Written By the Black Knight of Destruction

Written By the Black Knight of Destruction

댓글 달기

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