2012-11-12 6 views
0

나는 C를 배우기 시작했고, 내가 잘못하고있는 것을 이해하지 못합니다. 다음은 pid + ". data"를 반환하는 함수의 간단한 코드입니다.문자열 포인터를 반환

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

char * getfilename(){ 
    char name[60]; 
    sprintf(name,"%i.data",getpid()); 
    return name; 
} 

void main(){ 
    char* name = getfilename(); 
    printf("%s",name); 
} 

출력은 ��#�a입니다.

그래서 나는 뭔가 잘못하고 있다고 생각합니다. getfilename가 리턴 한 후

+1

정말로 모든 경고와 디버깅 정보를 얻으려면'gcc -Wall -g'로 컴파일해야합니다. GCC가 당신에게 경고했을 것입니다. 그리고 경고가 주어지지 않을 때까지 코드를 향상 시키면'gdb'를 사용하여 문제를 디버깅 할 수 있습니다. –

답변

4
char * getfilename(){ 
    char name[60]; 
    sprintf(name,"%i.data",getpid()); 
    return name; 
} 

당신은 name 개체에 액세스 할 수 없습니다. 자동 개체 name의 수명은 getfilename에서 마지막으로 }으로 끝납니다. 함수가 반환 된 후 액세스하면 정의되지 않은 동작이 발생합니다.

namestatic으로 지정하면 문제가 해결됩니다. 그러나 여러분이해야 할 일은 getfilename 함수가 파일 이름이 쓰여지는 포인터 인수를 받아들이도록하는 것입니다.

편집 :

이유는 strdup을 사용하지 않는 것이 좋습니다?

  • strdup은 표준 C 기능이 아닙니다. strdup은 POSIX 세계에 살고 있습니다. 가능한 경우 언제든지 이식성을 이유로 표준 C 함수를 사용하는 것을 선호합니다.
  • strdupmalloc 호출을 수행하므로 free을 수행하는 것을 잊지 않아야합니다. 이것은 결코 malloc (실제로는 이 으로 전화하기 위해으로 나타나지 않음)를 호출하지 않는 표준 C 라이브러리의 모든 기능과 반대입니다. strdup은 잘못된 API 디자인입니다.
  • strdup은 문자열의 복사본을 수행 중입니다. 왜 여분의 사본을 수행해야합니까? 문자열을 검색 할 수있는 장소에 씁니다. 스택에
1
char name[60] 

삶,하지만 한 때문에에 대한 참조가 (또한 getfilename()에 의해 반환) 무효가, 이후의 해제 getfilename() 내부되고있다.

1

char name[60]은 함수가 호출 될 때 할당되고 반환 할 때 할당 해제되는 로컬 변수입니다. 그것을 반환하려고하면 실제로 주소를 반환합니다 (모든 배열은 대부분 포인터 연산을위한 통어론입니다). 이제는 호출자가 메모리 블록에 대한 포인터를 가지고 있으므로 가비지가 포함될 가능성이 높습니다.

3

한 용액 strdup을 사용하는, 즉 변화율 :

return name; 

행 :

return strdup(name); 

이것은 동적 메모리 할당을 사용하여 일시적인 (로컬) 문자열의 복사본을 만드는 (즉 malloc).

당신이 그걸로 끝났 으면 물론 free이 문자열을 확실히해야합니다.

당신이 무엇을 필요가있다 : 그것은 (일반) 지역 변수이고, 그 때 함수 returnes을 정리 얻을 때문에

#include <string.h> // strdup() 
#include <stdlib.h> // free() 
+0

관련 헤더 파일을 포함하면 +1하겠습니다. – jpm

+0

@jpm : 확인 - 완료되었습니다. –

1

당신은, 당신의 기능 getfilename에서 배열 name을 반환 할 수 없습니다. 따라서 main으로 돌아가서 반환 된 값을 인쇄하려고하면 name 포인터는 다른 목적으로 다시 사용 된 메모리 블록을 참조합니다.

이 문제에 대한 몇 가지 솔루션이 있습니다

  1. getfilenamestaticname을 확인합니다. 이렇게하면 getfilename에 대한 호출이 더 오래 지속되며 안전하게 반환 될 수 있지만 getfilename에 대한 모든 호출이 동일한 버퍼를 사용한다는 단점이 있습니다.
  2. malloc 동적 배열을 할당 (당신이 그것으로 완료되면 free 그것을 정리하는 것을 잊지 마세요)
  3. 이 매개 변수의 값을 저장하는 버퍼를 전달합니다.
+0

가장 좋은 답변 중 하나. 하나의 질문, getfilename 호출시 동일한 버퍼를 사용할 때의 문제점은 무엇입니까? –

+0

이 특별한 경우에는 문제가 없습니다. 그러나이 코드를 상상해보십시오. char * one = getfilename(); char * two = getfilename();'여기서'getfilename'은 각 호출마다 다른 내용으로 버퍼를 채울 수 있습니다. –

0

다른 답변에서 언급했듯이 함수 스택의 어딘가를 가리키는 포인터를 반환 할 수 없습니다.

할당 된 배열을 getfilename() 함수에 전달하면됩니다. 다음과 같이 프로그램을 다시 작성할 수 있습니다.

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

void getfilename(char * name) 
{ 

    sprintf(name,"%i.data",getpid()); 
} 

int main(void) 
{ 
    char name[60]; 
    getfilename(name); 
    printf("%s\n",name); 
    return 0; 
} 

정상적으로 작동합니다.