Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get rid of "call is the same expression as the source" warning in C?

I would like to copy the argument strings into an array in the program. So I wrote the following code:

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

int main(int argc, char *argv[]){
    // go through each string in argv
    int i = 0;
    while(i < argc){
        printf("arg %d: %s\n", i, argv[i]);
        i++;
    }

    //let's make our own array of strings
    char *states[] = {"California", "Oregon", "Washington", "Texas"};
    int num_states = 4;
    i = 0;  //watch for this
    while(i < num_states) {
        printf("state %d: %s\n", i, states[i]);
        i++;
    }

    //copy argv into strings
    char **dst;
    dst = (char**)malloc(sizeof(char*)*argc);
    for(i = 0; i < argc; i++){
        dst[i] = (char*)malloc(sizeof(char)*sizeof(argv[i]));
    }

    i = 0;
    while(i < argc){
        strncpy(*dst+i, argv[i], sizeof(argv[i]));
        printf("*dst = %s\n", *dst+i);
        i++;
    }

    for(i = 0; i < argc; i++){
        free(dst[i]);
    }
    free(dst);
    return 0;
}

The code works fine. But there is a compilation warning:

cc -Wall -g -o ex11 ex11.c
ex11.c: In function ‘main’:
ex11.c:31:34: warning: argument to ‘sizeof’ in ‘strncpy’ call is the same expression as the source; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
   strncpy(*dst+i, argv[i], sizeof(argv[i]));

How can I get rid of this warning?

Update 1: I changed the allocation of the dst pointer into the following:

  for(i = 0; i < argc; i++){
    //dst[i] = (char*)malloc(sizeof(char)*sizeof(argv[i]));
    dst[i] = (char*)malloc(strlen(argv[i]+1));
  }
  // ignore malloc null return
  printf("test 1 = %d\n", sizeof(char)*sizeof(argv[i]));
  printf("test 2 = %d\n", strlen(argv[i]));

I want to know if test 1 and test 2 will generate the same number. But for test 2, it is complaining about segmentation fault. Why is that?

Update 2: Get rid of the malloc loop based on the comment:

  //copy argv into strings
  char **dst;
  dst = (char**)malloc(sizeof(char*)*argc);

  i = 0;
  while(i < argc){
    dst[i] = strdup(argv[i]);   //array version: strdup
    printf("*dst = %s\n", *(dst+i));
    i++;
  }
like image 373
drdot Avatar asked Dec 21 '14 05:12

drdot


1 Answers

The compiler is right, and telling you about a dangerous bug. You're using the size of a pointer, not the size of the string it points to. (The actual warning is saying you are specifying the length to copy based on the source, making strcpy act like strncpy. In this case it is wrong, though, because it didn't notice it is sizeof a pointer and not an array.)

You also had a serious error with *dst+i, which is the same as dst[0] + i, not dst[i]. You've got i independently allocated pointers, best to use them all.

You should instead use

dst[i] = (char*)malloc(strlen(argv[i]) + 1); // remember space for the NUL character

and

strcpy(dst[i], argv[i]);

or better yet, just

dst[i] = strdup(argv[i]);

which does the allocation and copy both.

like image 136
Ben Voigt Avatar answered Oct 21 '22 19:10

Ben Voigt