简体   繁体   中英

copy character string to an unsigned buffer: Segmentation fault

i am trying to copy two integers and a character string to a buffer and print the buffer elements out. I get a seg fault for the third printf statement:

    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];

I dont know why this would seg fault?

buffer[8] is a char , %s waits for string, meaning char * , pass &buffer[8] instead. You get segmentation fault because printf tries to treat a char as a pointer to char , which is address (and if a char is passed it's unlikely to be a valid one)

EDIT: as David commented, if the starting point for copying the string is related to the values before it, don't use a fixed value, instead of &buffer[8] use buffer+(2*sizeof(id)) or buffer[2*sizeof(id)]

The main problem is that you are trying to print the string by passing only a character. This is because buffer[8] refers to the char at index 8, not the string starting at that position. So you need to take the address of buffer[8] to make it a string or char* .

The reason why it segfaults is that printf attempts to print a string starting at the address given by the first char (ie. the string contents itself), which is not a valid pointer.

There are also number of typos and mistakes. A working version is below:

#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;
}

If you had compiled this app with all warnings enabled (ie. -Wall ), your compiler (at least GCC does) should warn you about your mistake like this:

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

Warnings should not be ignored!

There were several issues on your code, but the most important point is that memmove() does not copy the null character byte of the string.

The function does not check for any terminating null character in source - it always copies exactly num bytes.

This gives you two options:

  • Account for that while you are copying the stuff:

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

  • Or after the memory was copied, make sure the string ends with a '\0' (aka. 0 ) on your buffer:

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

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

Anyway, the code works now. Another issue was that you were trying to specify the length of the string with sizeof(str) . That's wrong, and you should be doing strlen(str) . One last thing, for clarity and security purposes don't do 2*sizeof(id) . If later you decide to change the variable type you are screwed. The right way wold be sizeof(id)+sizeof(len) . That's all.

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]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM