함수내에서 할당한 메모리를 그 함수 종료 후에도 사용하려고 하

indizarm의 이미지

보통 함수 안에서 할당받은 메모리는 함수가 종료되면

반환되는데, 어떻게 하면 함수 내에서 할당받은 메모리를

함수가 종료되어도 사용할 수 있을까요?

HeapAlloc()같은 함수 없습니까?

다음과 같은 방법으로는 절대로 안됩니다.

꼭 프로그래밍 언어 과목에서의 변수의 범위 문제 같군요. -_-;;

void man_str2(char* str)
{
        int len_str;
        int len_append;
        char* append = "What a Cool Days!!!";
        char* str_new;

        len_str = strlen(str);
        len_append = strlen(append);

        str_new = (char*)malloc(len_str + len_append);

        strcpy(str_new,str);
        strcat(str_new,append);

printf("\n\n\n함수의 안에서는");

        free(str);
        str = str_new;
puts(str);
printf("\n\n\n");
}
ifyou의 이미지

int main(void)
{
     char* s;
   
     s=(char*)malloc(100);
     strcpy(s,"hello");
     
     man_str2(s);   // <<======== 이 부분..

     printf("str:%s\n",s);
     
}


요런 식으로 했을때 제대로 안된다는 말이지요?

indizarm wrote:
void man_str(char* str)
{
               .........
        str = str_new;
               .........
}

문제는 여기 str=new_str 부분에 있습니다.


main()
{
        s=malloc();       // 여기서 s는 100번지를 할당 받음
        man_str2(s);    // 100번지를 넘겨줌
        printf("str:%s\n",s); // s는 100번지..
}

man_str(char* str)
{
       char* new_str;

       len=strlen(str);  // 여기서 str은 100번지..

       new_str=malloc();  // new_str은 200번지

      str=new_str;       // str은 200번지
       
}


결국은 포인터 문제인데..

.

indizarm의 이미지

그런데 단순히 포인터만의 문제가 아니라

할당된 메모리가 함수 종료 후에도 남아있어야

의미를 갖는 경우가 되겠습니다.

포인터, 특히 배열을 사용할 때에 헷갈리는

것이 배열의 이름이 포인터라는 것 때문에

무의식적으로 &배열이름 이런식으로 이중

포인터를 사용했는데, 의미 없는 일이었습니다.

What a Cool Days!!!

kuma의 이미지

함수를 종료한다고 Heap 이 풀린다는 이야기는 금시초문인데요, 그리고 제가 머리가 나빠서 그런지 몰라도 정확한 질문의 요지를 잘 모르겠군요. 다시한번 상세한 질문 부탁드립니다.

pynoos의 이미지

void man_str2(char* str) 

이것을..

char * man_str2(char* str) 

이렇게 바꾸어

char * man_str2(char* str) 
{
.
.
. 
        return new_str;
}

로 하지 않는 이유가 있나요?

indizarm의 이미지

func1()
{
      메모리 할당,
      변수 등등
}

func2()
{

      func1();
    
      이 위치에서는 func1()의 변수 및
      할당 받은 메모리가 heap으로 되돌려지지 않습니까?

}

그런데 제가 원하는 것은 func2()에서 func1()이 종료되는

것과는 상관없이 func1()에서 할당받은 메모리를 사용하고

싶다는 것이죠.

What a Cool Days!!!

moonzoo의 이미지

결론적으로는 pynoos님이 말씀하신 방법을 쓰신다면 간단히 해결될 듯

합니다.

또한 질문하신 것에 대해 ifyou님이 명확히 설명해 주셨는데..

간랸히 말하자면

=== main에서 ===
char * s;
man_str2(s); 에서의 s와...

=== 함수에서 ===
man_str2(char * str) 의 str은 엄연히 다른 변수인데
==> str = str_new 을 해놓고..

함수 밖에서 s를 사용하려던 것이 잘못 입니다.

malloc으로 잡은 메모리는 당연히 함수 밖에서도 유효합니다..

indizarm의 이미지

-_-;; 럴수. 안될꺼라고 생각했는데 되네. 당황스럽네

이거 어떻게 된거지...

char* type의 함수를 사용하려고 하다가 뭐 어짜피

배열의 이름 자체가 포인터인데 뭐어쩌랴.

그리고 할당된 메모리가 사라질 것이라고 생각했는데

그냥 살아있군요. 아, 진짜로 나는 novice인가?

제발 설명좀 해주세요. -_-;;;

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* man_str2(char* str);     // 문자열에 다른 메모리 블럭을 할당


int main()
{
        char* str;

        str = (char*)malloc(15); // 29);

        strcpy(str,"the CoolGuy!!! ");

        printf("원래의 문자열\n");
        puts(str);
        printf("\n\n");

        str = man_str2(str);

        printf("함수 호출 후의 문자열\n");
        puts(str);
        printf("\n\n");

        return 0;
}

char* man_str2(char* str)
{
        int len_str;
        int len_append;
        char* append = "What a Cool Days!!!";
        char* str_new;

        len_str = strlen(str);
        len_append = strlen(append);

        str_new = (char*)malloc(len_str + len_append);

        strcpy(str_new,str);
        strcat(str_new,append);

printf("\n\n\n함수의 안에서는");

        free(str);
//      str = str_new;
puts(str);
printf("\n\n\n");

        return str_new;
}

____________________(이하 실행 결과)
[indizarm@je2 str_test]$ ./str_test2
원래의 문자열
the CoolGuy!!!





함수의 안에서는



함수 호출 후의 문자열
the CoolGuy!!! What a Cool Days!!!

What a Cool Days!!!

indizarm의 이미지

음... 처음에 그렇게 생각해서 이중 포인터로

&str = &str_new 하니까 안되던데요.

주소의 주소 뭐 그렇게 생각하고 했는데 컴파일

에러가 뜨던데요

What a Cool Days!!!

halite의 이미지

넘겨 줄때 아예 포인터의 포인터를 넘겨주면 되겠죠?

void man_str2(char **str)
{
char *test = (char *)malloc(200);
printf("str : %s\n", *str);
free(*str);
*str = test;
}

void main()
{
char *s = (char *)malloc(100);

....
man_str2(&s);
....
}

indizarm의 이미지

방금 올린 코드가 제가 생각했던 대로 움직이는

코드입니다.

제가 당황스러운 것은 local에서 할당된 메모리가

그 블록이 종료되었음에도 불구하고 살아있다는 점

하고, char* man_str2()로 하니까 void man_str2()

로 할때 사라지지 않았던 메모리가 free되었다는 점

입니다.

What a Cool Days!!!

yui의 이미지

indizarm wrote:
방금 올린 코드가 제가 생각했던 대로 움직이는

코드입니다.

제가 당황스러운 것은 local에서 할당된 메모리가

그 블록이 종료되었음에도 불구하고 살아있다는 점

하고, char* man_str2()로 하니까 void man_str2()

로 할때 사라지지 않았던 메모리가 free되었다는 점

입니다.

지금 여러개를 동시에 헷갈려 하시는 것 같습니다.
정리하며 다음과 같습니다.

    1)다음과 같이 한 함수 안에서 malloc으로 메모리를 잡으면 char* s = malloc(100);
    이 100 바이트는 함수가 끝나도 남아있습니다.
    2) 문제는 이 100바이트의 "시작주소"를 어떻게 함수를 호출한 녀석에게 돌려줄 까 하는 겁니다.
      a) pynoos님 방법 : 리턴 값을 이용한다.
      b) halite님의 또다른 방법 : 값이 바뀌길 원하는 변수의 "주소"를 인자로 넘긴다. 함수내에서 이 주소값으로 직접 변수의 값을 바꾼다.

일단 heap에 잡은 메모리가 함수 호출후에도 남아있다는 것은 사실이므로 그냥 받아들여 주세요. -_-;

그리고 &str = &str_new와 같이 쓰신 것을 보니
아마 halite님의 방법을 원하시는 것 같은데...

void swap(int a, int b)
{
  int t = a; a = b; b = t;
}

로는 원하는 swap이 일어나지 않는 다는 것은 아시죠?

void swap(int* a, int* b)
{
  int t = *a; *a = *b; *b = t;
}

아시다시피 이렇게 해야 실제로 a와 b의 값이 바뀝니다.

자 이제 원래 코드로 돌아오면

void man_str2('문자열의 시작 주소값')
{
   free ('문자열의 시작 주소값');
   '문자열의 시작 주소값' = new malloc(100);
}

로 하면 될까요? 안됩니다.

halite님이 쓰신 것처럼,

void man_str2('문자열의 시작 주소값' 의 주소값)
{
   free (* '문자열의 시작 주소값'의 주소값)
  (* '문자열의 시작 주소값'의 주소값' = new malloc(100);
}

와 같이 해야 합니다.

설명이 쓸데 없이 길었습니다. 그럼.

[/][/][/][/]
ifyou의 이미지

예제 만들고 있는 도중에 모든 것이 다 올라와 버렸네요 :D

저는 c 배울때 그다지 어렵게 배웠고, 한때는 왠만한 포인터 문제는

척척 해결했었죠. 그런데, 오랫동안 사용 안하니까 헷갈리는 것도

많이 생깁니다.

프로그래밍을 하는 이상, 자신이 다루는 랭귀지가 포인터를 사용하지

않더라도 포인터에 대해서 알아 두는 것이 좋으리라 생각됩니다.

하면서 이것저것 얻게 되는 것도 많고요.. 한 번 확실히 알아 두면

헷갈려도 차근차근 생각해 보면 웬만한것은 다 답이 나옵니다~

댓글 달기

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