Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top