0

I implemented a generic quick sort and now I want to accept the array from command line. Following is a function that is supposed to copy character pointers from array argv to base. I am getting segmentation fault. The copy is working fine when I pass address of two integers.

#include<stdio.h>

void copy(void *src, void *dest, int size)
{
    char *s, *d;
    int i;

    s = src;
    d = dest;

    for(i = 0; i < size; i++)
        d[i] = s[i];
}

int main(int argc, char *argv[])
{
    void *base;
    int i = 10;
    int j = 20;

    printf("%d, %d\n", i, j);
    copy(&i, &j, sizeof(int));
    printf("%d, %d\n", i, j);

    copy(argv, base, sizeof(char *));

    return 0;
}

Output

10, 20
10, 10
Segmentation fault (core dumped)
Ajinkya
  • 826
  • 1
  • 10
  • 15

4 Answers4

2

argv is a pointer array. If you just want to copy the pointers you can do it like that:

 base = calloc( argc, sizeof(char *) );
 copy( argv, base, argc * sizeof(char *) );

Now you have copy of the pointer array argv, but that still contains pointers to the original arguments argv[i]. If you want to create copies of argv[i] too, dont use copy() but:

 char **base = calloc( argc, sizeof(char *) );
 int  i;

 for( i=0; i<argc; i++ )
     base[i] = strdup( argv[i] );

But remember: argv[0] is the program's name and I would bet you don't want that to be part of the array. To avoid it:

 base = calloc( argc-1, sizeof(char *) );
 copy( argv+1, base, (argc-1) * sizeof(char *) );

or

 char **base = calloc( argc, sizeof(char *) );
 int  i;

 for( i=1; i<argc; i++ )
     base[i-1] = strdup( argv[i] );
Ingo Leonhardt
  • 9,435
  • 2
  • 24
  • 33
1

You are trying to copy sizeof(char*) bytes to where base is pointing to. But you did not allocate any memory to base so the program invokes undefined behaviour.

alk
  • 69,737
  • 10
  • 105
  • 255
0
void *base = malloc(strlen(argv[0])+1);

then

copy(argv[0], base, strlen(argv[0])+1);

at the end

free(base);

sizeof(char*) will return a size of a single pointer, not the whole path

Edit:

void *base;
int i;

if (argc>0)
{
   base = malloc(argc+1);// we have enough pointers for copying args (+1 to null terminat it)

   for(i=0; i < argc; i++)
   {
      base[i] = malloc(strlen(argv[i])+1);
      copy(argv[i], base[i], strlen(argv[i])+1);
   }
   base[i] = NULL;
}

base will be a double pointer holding all arguments

you may do memset(...) and memcopy(...) btw

aah134
  • 860
  • 12
  • 25
  • using strlen(argv[0]) will effectively get you the name of your program, not the arguments following (from argv[1] to argv[argc-1]). – George Mitchell Sep 19 '13 at 14:27
  • you just like to downvote everyone, plus he want to test the copying function he made. argv[0] has a pinter to a string with the application name. I didnt care of your assumption -> "argv[1] to argv[argc-1]" – aah134 Sep 19 '13 at 14:31
  • 1
    "I want to accept the array from command line.", "...is supposed to copy **character pointers** from array argv to base". He already tested his `copy` function with the int swapping (and it is also trivial to check its correctness). "you just like to downvote everyone": you're aware that a downvote on an answer costs rep, right? Your answer and John's answer are incorrect with respect to the OP. Edit to correct or clarify your answer and I will remove the downvote. In all actuality, I give upvotes more freely than I give downvotes :p (the ratio is about 1:4 downvotes to upvotes) – George Mitchell Sep 19 '13 at 14:45
  • ok thanks, I am just answering one part of the problem, which is allocating memory for a copy to not get a memory fault. – aah134 Sep 19 '13 at 14:49
  • one thing left: in your code you should call `copy(argv[i], base[i], strlen(argv[i])+1);` as `malloc()` doesn't initialize the allocated memory – Ingo Leonhardt Sep 19 '13 at 14:59
  • 1
    and a typo I've seen just now: in `base[i] = malloc(strlen(argv[0])+1);` it must be `argv[i]` of course – Ingo Leonhardt Sep 19 '13 at 15:21
-1

Argv is not a single pointer, its a double pointer,

you should be doing like this:

base = calloc(1, sizeof(char *));
copy(argv[1], base, sizeof(char *));

if you really want to copy the full argv, you have to replace the sizeof(char *) with strlen(argv[0]) and have to allocate base with the length of the argv[0].

John
  • 449
  • 5
  • 12
  • 1
    using `strlen(argv[0])` will effectively get you the name of your program, not the arguments following (from argv[1] to argv[argc-1]). – George Mitchell Sep 19 '13 at 14:19