简体   繁体   中英

segmentation fault in my code with strcpy

I am getting segmentation fault after strcpy(buffer_two, argv[1]); Not sure what's going wrong here and i would appreciate a hand to understand what's wrong and why i get that segmentation fault.

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

int main(int argc, char *argv[])
{
    int value = 5;
    char buffer_one[8], buffer_two[8];

    strcpy(buffer_one, "one"); // Put "one" into buffer_one
    strcpy(buffer_two, "two"); // Put "two" into buffer_two
    printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
    printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);

    printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1])); //Copy first argument into buffer_two

    strcpy(buffer_two, argv[1]); // <---- here

    printf("[After] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
    printf("[After] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
    printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value);     
}

There are two possible reasons for the seg fault.

1) There is no argv[1] , ie you try to copy from a NULL pointer (That is... If the program is started with no arguments, argv[1] may be accessed but will return a NULL pointer. Consequently, copying from it is illegal and may cause a seg fault). So if you start the program like ./program the program will crash as argv[1] is NULL

2) The length of argv[1] exceeds the destination, ie 7 chars and a terminating NUL. If so you write out of bounds and may cause a seg fault.

So to get the code correct do:

int main(int argv,char * argv[])
{
    char buffer_two[8];
    if ((argc >  1) && (strlen(argv[1]) < 8)) // Make sure arg[1] is there
                                              // Make sure it's not too long
    {
            strcpy(buffer_two, argv[1]);
    }
    else
    {
        printf("Illegal start of program\n");
    }
    return 0;
}

BTW

When printing a pointer using %p make sure to cast to void*

So this

printf("[After] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);

should be

printf("[After] buffer_two is at %p and contains \'%s\'\n", (void*)buffer_two, buffer_two);

There are two primary problems here: you do not check argc to see if argv[1] exists, and you blindly copy argv[1] into the buffer that might not be big enough to fit it. I've also fixed some of the compiler warnings related to your printf statements. Here is an example, using your code, of how to handle such things:

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

int main(int argc, char *argv[])
{
   if(argc < 2) {
      printf("Please enter an argument when invoking this program\n");
      return EXIT_FAILURE;
   }
    int value = 5;
    char buffer_one[8], buffer_two[8];

    strcpy(buffer_one, "one"); // Put "one" into buffer_one
    strcpy(buffer_two, "two"); // Put "two" into buffer_two
    printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", (void *)buffer_two, buffer_two);
    printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", (void *)buffer_one, buffer_one);

    printf("\n[STRCPY] copying %zu bytes into buffer_two\n\n", strlen(argv[1])); //Copy first argument into buffer_two

    strncpy(buffer_two, argv[1], 8); // <---- here
    if(buffer_two[7] != '\0'){
       printf("[ERROR] string did not fit into buffer, truncating\n");
       buffer_two[7] = '\0';
    }

    printf("[After] buffer_two is at %p and contains \'%s\'\n", (void *)buffer_two, buffer_two);
    printf("[After] buffer_one is at %p and contains \'%s\'\n", (void *)buffer_one, buffer_one);
    printf("[AFTER] value is at %p and is %d (0x%08x)\n", (void *)&value, value, value);     
}

Check argc value before using argv. Use strcpy only when argc >1 . Make a conditional statement before strcpy()

Eg...

int main(int argv,char * argv[])
{
    char buffer[10];
    if (argc >  1 && strlen(argv[1]) < 10)
    {
        strcpy(&buffer[0],argv[1]);
    }
    return 0;
}

You should run program by

./a.out hai

hai is the argument passed. Here argc is 2 ,argv[1] = hai

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