2013-05-06 1 views
1
char a[3], b[3]; 
strcpy(a,"abc"); 
printf("a1 = %s\n", a); 
strcpy(b,a); 
printf("a2 = %s\n", a); 
printf("b = %s\n", b); 

처럼 행동 출력은 다음과 같습니다 의 strcpy : 더 내가 일을 strcpy를 이해하는 방법에서 'strcut'

a1 = abc 
a2 = abc 
b = abc 

가 대신 내가 두 번째 strcpy를 부르는 이유 때

a1 = abc 
a2 = 
b = abc 

를 얻을

시간은 (분명히) 내용을 지우나요?

감사

답변

3

이것은 buffer overflow 문제 - 당신의 ab은 null 종결을위한 공간이없는 – 너무 짧다. 무슨 일이 일어나고 a은 메모리에 b 직후이므로 strcpy(b,a)이 실행될 때 b의 끝에 저장된 널 터미네이터는 실제로 a의 첫 번째 문자와 동일한 메모리 위치입니다. 이로 인해 a이 갑자기 빈 문자열이됩니다.

우선 들어

는 배열 대신 3 4이 샌드 박스/재생/학습 모드에서 괜찮의 길이를 만들지 만, 생산 코드에 고려해야합니다 (예 : strncpy)에

  • 사용 안전한 문자열 함수 버퍼 오버 플로우를 피하십시오.
  • 데이터 크기에 맞춰 가변 크기 또는 사전 계산을 지원하는 문자 배열/버퍼를 사용하십시오. 당신 배열이 너무 작아서 및 복사를 중지 할 때 모르는 strcpy 이후 ba을 복사하려고 할 때 가장 가능성이 a 덮어 쓰는 null 종결을위한 공간을 가지고 있지 않기 때문에
+0

감사합니다. 나는 알고 있어야 할 것이지만 문제의 근원이라면 나는 다른 오류를 겪었을 것이라고 생각했습니다. 당신 (또는 다른 사람)이 이것이 왜 특정 장소에서만 문제를 일으키는 지에 대해 더 많은 설명을 할 수 있습니까? (예를 들어 "abc"를 배열 'a'에 intially copy 할 때) –

+0

@ liam-fisher 이유를 설명하기 위해 내 대답을 업데이트하겠습니다. –

+0

@ liam-fisher는 처음에 'abc "배열에'a'를 지정합니다. 왜냐하면 여전히 버퍼 오버런이지만 코드에 다른 변수가 없으므로 사용중인 것은 메모리의'a' 바로 뒤에 있습니다. 그러나 이것은 여전히 ​​메모리를 손상시키고 뒤에 코드에서 이상한 충돌과 같이 코드가 실행 된 후 이상한 행동을하게됩니다. –

1

. 이 선언은이 특정 프로그램에 대한 문제를 해결하는 것 :

char a[4], b[4]; 

을 당신이 당신의 목적지가 소스뿐만 아니라 null 종결을 수용 할 공간이 충분히이 있는지 확인해야하는 일반적인 경우.

이 예제는 어떤 일이 벌어지고 있는지 더 잘 이해할 수있게 해줍니다. 이는 데모 용 일 뿐이며, 이와 같은 코드를 다른 용도로 사용해야하지만 배워야합니다. 이 ideone에 나를 위해 작동하고 당신은 here을 사는 경우에 볼 수 있지만 우리가 정의되지 않은 동작을 호출하기 때문에 다른 컴파일러에서 제대로 작동하지 않을 수 있습니다

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

int main() 
{ 
    char a[3], b[4]; 

    // a will have a lower address in memory than b 
    printf("%p %p\n", a, b); 

    // "abc" is a null terminated literal use a size of 4 to force a copy of null 
    strncpy(a,"abc",4); 
    // printf will not overrun buffer since we terminated it 
    printf("a2 = %s\n", a); 

    // explicitly only copy 3 bytes 
    strncpy(b,a,3); 
    // manually null terminate b 
    b[3] = '\0' ; 

    // So we can prove we are seeing b's contents 
    b[0] = 'z' ; 

    // This will overrun into b now since b[0] is no longer null 
    printf("a2 = %s\n", a); 
    printf("b = %s\n", b); 
} 
+0

"이 선언은이 짧은 예제 문자열 세트의 문제를 해결할 것입니다."일반적으로 목적지가 –

+0

@ElchononEdelson 명확한 답변 수정 –

0

첫 번째 strcpy(a,"abc") 이미 잘못된 것입니다. char 배열과 C-String을 혼동하지 마십시오 ... C-String은 항상 char 배열이지만 char 배열은 항상 C-String이 아닙니다.

C 문자열의 끝에는 '\0' 문자가 있어야합니다. 따라서 strcpy "abc"-> a [3]을 수행하면 실제적으로 다음과 같이 이동합니다. 바이트 배열 { 'a', 'b', c ','0 '}

및 B 함께 생성 된, B 바로 앞서 이다.당신이 을 인쇄 할 때 잘못에도 불구하고 당신의 '\0' 문자가 B로 예약 된 영역이기 때문에의 printf()가 여전히 ..., 문자열의 끝으로 식별 할 수있는 '\0'을 찾을 수 있기 때문에이 경우 IN 잘 간다.

다음 문제는 모두 동일한 문제와 관련이 있습니다 ... 해결책은 다음과 같습니다. C 문자열에 대한 버퍼가 문자열의 최대 크기 + 1이어야하므로 사용자가 '\0' char. 자세한 내용이 필요하면 "C-String"또는 "null-terminated string"에 대해 Google에 문의하십시오.

0

매우 일반적인 초보자 실수입니다. C에는 문자열 프리미티브가 없습니다. 우리가 문자열에 관해 이야기 할 때, 우리는 실제로 null로 끝나는 문자 배열 (또는 버퍼, 나는 당신이 좋아하는 명명법을 신경 쓰지 않는다)에 대해 이야기하고있다. 따라서 char [3]은 널 문자 2 개와 null 종결자를 포함합니다. 또 다른 미묘한 문제는 메모리에서 스택에 [0] [1] [2] b [0] b [1] b [2]로 배치된다는 것입니다. 네가받을 자격이되었을 때 추락했다. "abc"는 정말로 "abc \ 0"이므로 a [3] == c 및 b [0] == \ 0이고 문자열이 겹칠 때 동작이 정의되지 않으므로 (예 : \ 0을 복사 할 때까지 그냥 복사 된 문자. 즉, strcpy (a, b)는 빈 문자열이됩니다.

반면에 프로그램은 작성된대로 작동합니다. 당신이 쓴 것은 당신이 의미 한 것이 아닙니다.

+0

null 종료 문자열의 개념을 이해합니다. 문자 배열을 [ 3]은 널 문자에 대해 네 번째 항목을 추가로 포함하므로이 점을 분명히 한 모든 사람에게 감사드립니다. 아직도 이해할 수없는 것은 'a'가 공백이되는 이유와 b가 의도 한대로 인쇄하는 이유입니다. 만약 당신이 말한대로 내 구현이 작동한다면, strcpy (b, a)는 abcabc \ 0을 포함하는이 두 배열의 메모리가 될 것이다. 'abcabc'로 인쇄하지 않았습니까? –

+0

디버거에서 실제 메모리 변화를 관찰하여 어디에 쓰여지는지 직접 볼 수 있습니다. 무엇입니까? B는 어디에 있습니까? 왜? 너 자신을 위해 그것을 볼 때 더 쉬울 것이다 :) –