2009-09-14 4 views
6

C/C++ 함수가 문자 배열 (std :: string과 반대)을 반환하도록하려면 char * 대신 const char *를 반환해야한다고 읽었습니다. 후자를 실행하면 프로그램이 중단 될 수 있습니다.반환 유형에서 const char * 대신 char *을 사용하면 크래시가 발생합니까?

아무도 이것이 사실인지 아닌지 설명 할 수 있습니까? 그것이 사실이라면, 함수에서 char *를 그렇게 위험한 것으로 반환하는 이유는 무엇입니까? 고맙습니다.

const char * my_function() 
{ 
    .... 
} 

void main(void) 
{ 
    char x[] = my_function(); 
} 
+6

main()은 항상 int를 반환해야합니다! http://users.aber.ac.uk/auj/voidmain.shtml – nmuntz

답변

14

있을 것입니다. 이것들은 실행 파일 자체의 읽기 전용 섹션으로 컴파일되기 때문에 malloc에 ​​의해 힙에 할당 될 필요가 없습니다.

예 :

const char* errstr(int err) 
{ 
    switch(err) { 
     case 1: return "error 1"; 
     case 2: return "error 2"; 
     case 3: return "error 3"; 
     case 255: return "error 255 to make this sparse so people don't ask me why I didn't use an array of const char*"; 
     default: return "unknown error"; 
    } 
} 
+0

또한 이것들이 구속되어 있고 다른 변수가 동일한 위치를 가리킬 수 있다는 점도 완전해야합니다. 하지만 const가 존중되면 문제가되지는 않습니다. –

2

char *가 스택에 할당되면 매달린 포인터를 반환합니다. 그렇지 않으면 함수의 프로토 타입과 일치하고 선언이 반환 값과 일치하는 한 괜찮습니다.

11

귀하가 들었던 내용은 이 아니며이 아닙니다.

const char *을 반환하면 char *을 반환해도 문제가없는 기능의 의미를 향상시킬 수 있습니다 (즉, 내가 제공 한 것을 사용하지 마십시오).

그러나, 어떤 경우에, 당신은 당신을 위해, 메모리 (즉 malloc 또는 new을 사용하여 할당) my_function에 힙에 할당 된 char * 또는 const char *, 그렇지 않으면 때마다 my_function 수익을 돌려 있는지 확인해야합니다 [const] char *이 할당 해제되고 잘못된 포인터에 액세스하게됩니다.

그리고 마지막으로 당신은 free 또는 delete 당신이 그것으로 완료하거나 메모리 누출 일단에 반환 한 경우 년대 [const] char *을 기억해야합니다. C/C++ 같은 훌륭한 언어가 아닌가?

그래서, C에서, 당신은 당신이 "문자열 리터럴"를 반환하는 함수가있는 경우 다음이 * const를 문자를 반환해야합니다

const char *my_function() { 
    const char *my_str = (const char *)malloc(MY_STR_LEN + 1); // +1 for null terminator. 
    /* ... */ 
    return my_str; 
} 

int main() { 
    const char *my_str = my_function(); 
    /* ... */ 
    free(my_str); 
    /* ... */ 
    return 0; 
} 
+1

그런 종류의 일은 C++의 std :: string (문자열 클래스 정의의 나쁜 해킹 작업 임에도 불구하고)과 스마트 포인터 . C에서 많은 고통을 겪을 필요가 있습니다. –

+0

@DavidThornley 적절한 문서는 그 고통을 거의 제로로 감소시킵니다. – Qix

1

단순히 리턴 코드를 변경하면 충돌이 발생하지 않습니다. 그러나 반환하는 문자열이 정적 인 경우 (예 : return "AString") const char *을 반환해야 컴파일러가 해당 메모리 수정 시도를 감지했는지 확인하고 으로 인해 충돌이 발생할 수 있습니다. 컴파일러 검사를 통과하기 위해 캐스트 등을 사용할 수는 있지만이 경우에는 으로 작업해야 충돌이 발생합니다.

+0

감사합니다. 리터럴 문자열 (예 : "This is a test";)을 반환하면 반환 유형은 const char *이어야합니다. 반환 유형이 char * 인 경우 위험 할 수있는 것은 무엇입니까? – Andy

+0

문자열이 수정되지 않으면 위험하지 않지만 호출자가 문자열을 수정하려고하면 응용 프로그램이 중단됩니다. 반환 유형이'const char *'이면, 컴파일러는 당신이 그것을 수정하도록하지 않을 것이다. –

+0

감사합니다. 아마 그들이 말한 내용 일 것입니다. C의 또 다른 측면은 몰랐습니다 (그리고 std :: string에 세 건배는 대단합니다!). – Andy

4

일반적으로 문제는 아니지만 고려해야 할 사항이 있습니다. 일반적으로 const-correctness의 문제입니다. 이는 변경할 수있는 항목과 불가능한 항목을 추적하는 것을 의미합니다.

큰 따옴표로 묶인 문자열을 반환하는 경우 const char *이고 다른 것으로 처리하면 문제가 발생합니다. 이러한 문자열을 변경하는 것은 정의되지 않은 동작이지만 일반적으로 프로그램이 참조 된 모든 위치에서 해당 문자열을 중단 시키거나 변경합니다.

스택 (즉, 호출 된 함수의 로컬 변수)에 문자 배열을 반환하면 포인터가 아무 것도 가리 키지 않습니다. 아마도 언젠가는 나쁜 결과를 초래할 수 있습니다.

호출 된 함수가 이미 const char * 인 것을 반환하는 경우 char *으로 변경하면 캐스트가 필요합니다. 또한 실제로 변경하려는 경우 변경할 수 있어야합니다. 보통 const char *으로 유지하는 것이 훨씬 좋습니다.

malloc() 또는 new로 할당 된 메모리를 반환과 즉각적인 문제는 없다,하지만 당신은 소유권의 문제가 수행 free()/delete 그것을, 당신은 가능한 사본에 대해 무엇을 어떤 기능을 하는가해야을? 이것은 C++의 스마트 포인터가 빛나는 곳입니다.

관련 문제