오류: 함수가 로컬 변수의 주소를 반환합니다.
저는 C는 초급이고 독학으로 배우고 있습니다.다음 기능을 만들고 있습니다.
char *foo(int x){
if(x < 0){
char a[1000];
char b = "blah";
x = x - 1;
char *c = foo(x);
strcpy(a, b);
strcat(a, c);
return a;
}
blah ...
}
기본적으로 부가된 문자열을 반환하려고 하는데 다음 오류가 나타납니다.
"error: function returns address of local variable?" (로컬 변수의 주소를 반환함) 제안사항, 수정 방법
로컬 변수는 정의된 블록 내에서만 연장되는 수명을 가집니다.제어가 로컬 변수가 정의되어 있는 블록 밖으로 나가는 순간 변수의 저장소는 더 이상 할당되지 않습니다(보증되지 않음).따라서 변수의 메모리주소를 변수의 라이프타임 영역 밖에서 사용하는 것은 정의되지 않은 동작이 됩니다.
한편, 다음의 조작을 실시할 수 있습니다.
char *str_to_ret = malloc (sizeof (char) * required_size);
.
.
.
return str_to_ret;
또,str_to_ret
대신.그리고 언제return
입력str_to_ret
, 에 의해 할당된 주소malloc
반환됩니다.에 의해 할당된 메모리malloc
힙에서 할당됩니다.히프에는 프로그램 실행 전체에 걸친 라이프타임이 있습니다.따라서 프로그램 실행 중 임의의 블록에서 언제든지 메모리 위치에 액세스할 수 있습니다.
또, 메모리 블록의 할당을 완료한 후에는, 다음의 순서에 따라 주세요.free
메모리 누전으로부터 보호합니다.메모리를 해방하면, 그 블록에 다시 액세스 할 수 없습니다.
저는 이 간단하고 간단한 코드 예를 생각해 냈습니다(그럴 수 있으면 좋겠다고 생각합니다.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* function header definitions */
char* getString(); //<- with malloc (good practice)
char * getStringNoMalloc(); //<- without malloc (fails! don't do this!)
void getStringCallByRef(char* reference); //<- callbyref (good practice)
/* the main */
int main(int argc, char*argv[]) {
//######### calling with malloc
char * a = getString();
printf("MALLOC ### a = %s \n", a);
free(a);
//######### calling without malloc
char * b = getStringNoMalloc();
printf("NO MALLOC ### b = %s \n", b); //this doesnt work, question to yourself: WHY?
//HINT: the warning says that a local reference is returned. ??!
//NO free here!
//######### call-by-reference
char c[100];
getStringCallByRef(c);
printf("CALLBYREF ### c = %s \n", c);
return 0;
}
//WITH malloc
char* getString() {
char * string;
string = malloc(sizeof(char)*100);
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
printf("string : '%s'\n", string);
return string;
}
//WITHOUT malloc (watch how it does not work this time)
char* getStringNoMalloc() {
char string[100] = {};
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", string);
return string; //but after returning.. it is NULL? :)
}
// ..and the call-by-reference way to do it (prefered)
void getStringCallByRef(char* reference) {
strcat(reference, "bla");
strcat(reference, "/");
strcat(reference, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", reference);
//OUTSIDE it is also OK because we hand over a reference defined in MAIN
// and not defined in this scope (local), which is destroyed after the function finished
}
컴파일할 때 [의도] 경고가 표시됩니다.
me@box:~$ gcc -o example.o example.c
example.c: In function ‘getStringNoMalloc’:
example.c:58:16: warning: function returns address of local variable [-Wreturn-local-addr]
return string; //but after returning.. it is NULL? :)
^~~~~~
...우리가 여기서 논의하는 것을 이해하라!
이 예를 실행하면 다음 출력이 생성됩니다.
me@box:~$ ./example.o
string : 'bla/blub'
MALLOC ### a = bla/blub
string : 'bla/blub'
NO MALLOC ### b = (null)
string : 'bla/blub'
CALLBYREF ### c = bla/blub
이론:
사용자 @phoxis는 이에 매우 잘 대답했습니다.기본적으로 다음과 같이 생각할 수 있습니다.{ ~ } 사이의 모든 것은 로컬 범위이므로 C-Standard는 외부에서 "정의되지 않음"이 됩니다.malloc를 사용하면 STACK(함수 범위)가 아닌 HEAP(프로그래밍 범위)에서 메모리를 얻을 수 있습니다.이것에 의해, 외부로부터 「표시」두 번째 올바른 방법은 Call-by-reference입니다.여기서 부모 스코프 내의 var를 정의하면 부모 스코프가 main()이기 때문에 STACK이 사용됩니다.
요약:.
세 가지 방법 중 하나는 거짓입니다.C는 함수가 동적 크기의 문자열을 반환하는 것만으로는 다소 서투릅니다.malloc하고 나서 풀어주든지 아니면 신원 조회로 연락해야 해또는 C++ 를 사용합니다.
malloc도 call by reference도 필요 없습니다.함수 내에서 포인터를 선언하고 반환할 문자열/배열로 설정할 수 있습니다.
@Gewure의 코드를 기본으로 사용합니다.
char *getStringNoMalloc(void){
char string[100] = {};
char *s_ptr = string;
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", string);
return s_ptr;
}
완벽하게 동작합니다.
첫 번째 질문에서 코드의 루프 버전이 아닌 경우:
char *foo(int x){
char a[1000];
char *a_ptr = a;
char *b = "blah";
strcpy(a, b);
return a_ptr;
}
char b = "blah";
다음 항목이어야 합니다.
char *b = "blah";
a
는 함수의 로컬 배열입니다.함수가 반환되면 해당 함수는 존재하지 않으므로 로컬 변수의 주소를 반환하지 마십시오.
바꿔 말하면, 의 생애는a
내에 있다(영역 내에 (영역내){
,}
이 함수에 포인터를 반환하면 유효하지 않은 메모리를 가리키는 포인터입니다.이러한 변수는 수명이 자동으로 관리되므로 명시적으로 관리할 필요가 없기 때문에 자동 변수라고도 합니다.
변수를 확장하여 함수의 범위를 넘어 지속되도록 해야 하므로 힙에 배열을 할당하고 포인터를 반환해야 합니다.
char *a = malloc(1000);
배열 " " "a
는, 「기억」이라고 부를 까지, 에 보존됩니다.free()
같은 주소에 있습니다.
잊지 마십시오.그렇지 않으면 메모리 누수가 발생합니다.
다음 행:
char b = "blah";
좋지 않습니다. lvalue가 포인터여야 합니다.
재귀 검사에서 x의 감소 값을 제한하지 않기 때문에 코드도 스택 오버플로의 위험에 처해 있습니다.
메세지는, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」의 에러 메세지가 표시됩니다.char a
변수입니다.즉, 「이렇게 하다」라고 하는 입니다.return
더 이상 존재하지 않게 될 거야.자동 변수가 아닌 다른 변수가 필요합니다.
a
는 함수에서 로컬로 정의되며 함수 외부에서 사용할 수 없습니다.할 char
함수에서 어레이를 동적으로 할당해야 합니다.
char *a = malloc(1000);
어느 에서 콜을 합니다.free
를 클릭합니다.
거예요.char b = "blah";
을 에 . : 에 리터럴을 할당하려고 합니다char
.
모든 답이 그 문제를 아주 잘 설명해 준다.
다만, 다른 정보를 추가하고 싶습니다.
함수의 출력을 벡터로 하고 싶은 순간에도 같은 문제에 직면했습니다.
이 경우 일반적인 해결책은 출력을 함수 자체의 인수로 선언하는 것입니다. 하면, 「 」는alloc
정보 저장에 필요한 변수 및 물리적 공간은 기능 외부에서 관리됩니다.기존 솔루션을 설명하는 의사 코드는 다음과 같습니다.
void function(int input, int* output){
//...
output[0] = something;
output[1] = somethig_else;
//...
return;
}
이 경우 질문 내 예제 코드를 다음과 같이 변경해야 합니다.
void foo(int x, char* a){
if(x < 0){
char b = "blah";
//...
strcpy(a, b);
//..
return;
}
//..
}
언급URL : https://stackoverflow.com/questions/12380758/error-function-returns-address-of-local-variable
'programing' 카테고리의 다른 글
Java 보안:잘못된 키 크기 또는 기본 매개 변수입니까? (0) | 2022.08.17 |
---|---|
gcc를 사용하여 __uint128_t 번호를 인쇄하는 방법 (0) | 2022.08.17 |
어레이를 컨트롤러에서 vue.js v-for로 전달하는 방법 (0) | 2022.08.10 |
"continue" 키워드는 무엇이며 Java에서는 어떻게 동작합니까? (0) | 2022.08.10 |
디버거를 사용하지 않는 경우에만 segfault가 발생합니다. (0) | 2022.08.10 |