2011-04-28 3 views
0

두 개의 정수와 문자열을 버퍼에 복사하고 버퍼 요소를 인쇄하려고합니다. 세 번째 printf 문에 대한 seg 오류가 발생합니다.부호없는 버퍼에 문자열 복사 : 분할 오류

id = 102; 
    len = 3; 
    str = "working"; 
    memmove(buffer,&message_id,sizeof(id)); 
    memmove(buffer+(sizeof(id)),&len,sizeof(len)); 
    memmove(buffer+(2*sizeof(id)),&string, sizeof(str)); 

    printf("1 is: %d\n", buffer[0]); 
    printf("2 is: %d\n", buffer[4]); 
    printf("3 is %s\n, buffer[8])); // here is where i get the seg fault should 
    be a string 
    /***/ 
    bufer is declared as unsinged char buffer[444]; 

왜 이것이 오류입니까?

+0

이 "F"로 버퍼로 선언 된 것입니다 - 당신이 bufer가 [444] – Hogan

+0

방법 * 문자열 서명 숯불이다라고 *와 * STR * 선언? – karlphillip

답변

1

코드에 몇 가지 문제가 있지만 가장 중요한 점은 memmove()이 문자열의 null 문자 바이트를 복사하지 않는다는 것입니다.

The function 소스의 종결 null 문자를 확인하지 않습니다. 항상 정확하게 num 바이트를 복사합니다. 그것에 대해

  • 계정 당신이 물건을 복사하는 동안 : 메모리를 복사 한 후
    • 또는

    memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str) +1);

    이 있는지 확인

이것은 당신에게 두 가지 옵션을 제공합니다 문자열은 '\0' (aka.당신의 버퍼에 0는) :

memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str));

buffer[sizeof(id)+ sizeof(len) + strlen(str) + 1] = 0;

어쨌든, 코드가 작동합니다. 또 다른 문제는 문자열의 길이를 sizeof(str)으로 지정하려고했다는 것입니다. 그게 잘못이고, 너는 strlen(str)을해야만한다. 마지막으로, 명확성과 보안을 위해 2*sizeof(id)을 사용하지 마십시오. 나중에 변수 유형을 변경하기로 결정했다면 당신은 망가졌습니다. 올바른 길은 sizeof(id)+sizeof(len)입니다. 그게 다야.

int id = 102; 
int len = 3; 
char* str = "working"; 
char buffer[444]; 

memmove(buffer,&id,sizeof(id)); 
memmove(buffer+(sizeof(id)), &len, sizeof(len)); 
memmove(buffer+sizeof(id)+sizeof(len), str, strlen(str)); 
buffer[sizeof(id)+ sizeof(len) + strlen(str) + 1] = 0; 

printf("1 is: %d\n", buffer[0]); 
printf("2 is: %d\n", buffer[4]); 
printf("3 is: %s\n", &buffer[8]); 
+0

위대한 설명. 고맙습니다. null 문자에 strlen 및 계정을 사용하는 것을 잊었습니다. – Warz

4

buffer[8]char이고, %s은 문자열을 기다립니다. 즉, char *을 의미합니다. 대신 &buffer[8]을 전달합니다. 주석 다윗 : printf와 주소입니다를 숯불하는 포인터로 문자을 치료하려고하기 때문에 당신은 세그먼트 오류를 ​​얻을 수

EDIT (숯불이 전달되는 경우는 유효 하나가 될 확률이 낮다) 문자열을 복사하는 시작점이 그 전 값으로 관련되는 경우, 대신 &buffer[8] 사용 buffer+(2*sizeof(id)) 또는 buffer[2*sizeof(id)]

+0

+1,'buffer + 8' 또는 더 나은 아직'buffer + 2 * sizeof (int) '가 바람직합니다. –

+0

@David - 당신 말이 맞아요, 주석 주셔서 감사합니다. – MByD

1

주요 문제, 고정 된 값을 사용하지 않는 당신이 전달하여 문자열을 인쇄 할 것입니다 오직 한 문자. 이는 buffer[8]이 색인 8에서 char을 나타내며 해당 위치에서 시작하는 문자열이 아니기 때문입니다. 따라서 문자열을 만들려면 buffer[8]의 주소를 가져 가야합니다 (char*).

segfaults 이유는 printf이 유효한 포인터가 아닌 첫 번째 문자 (즉, 문자열 내용 자체)에 의해 주어진 주소에서 시작하는 문자열을 인쇄하려고 시도하기 때문입니다.

오타 및 실수도 많이 있습니다. 작업 버전은 아래와 같습니다. (즉, -Wall) :

problem.c:18: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’ 

#include <stdio.h> 
#include <memory.h> 

int main() 
{ 
    unsigned char buffer[444]; 
    int id = 102; 
    int len = 3; 
    char* str = "working"; 

    memmove(buffer,&id,sizeof(id)); 
    memmove(buffer+(sizeof(id)),&len,sizeof(len)); 
    memmove(buffer+(2*sizeof(id)), str, sizeof(str)); 

    printf("1 is: %d\n", buffer[0]); 
    printf("2 is: %d\n", buffer[4]); 
    printf("3 is %s\n", &buffer[8]); 

    return 0; 
} 

당신이 당신의 컴파일러는 (적어도 GCC는 않음)이 같이 당신의 실수에 대해 경고해야 사용할 수있는 모든 경고와 함께이 응용 프로그램을 컴파일 한 경우

경고를 무시해서는 안됩니다.