-1

I'm trying to copy the individual elements of argv into a 2nd array. I'm using strncpy to do it.

Here's a stripped version that replicates the problem.

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

int main(int argc, char *argv[])
{
    printf("%d\n", argc);
    char *argvarray[argc];
    int arrlen;

    //int j;
    for(int j=0; j< argc; j++){
        arrlen = arrlen + strlen(argv[j]);
    }

    printf("size of argv: %d\n", arrlen); //see if size is right
    strncpy(*argvarray, *argv, arrlen);

    for(int j=0; j< argc; j++){
        printf("value of j: %d\n", j); //to see what's going on
        printf("%s\n", argv[j]); 
        printf("%s\n", argvarray[j]); //gets 1st element no problem
    }

    return 0;
}

If I pass 1 arg to main it copies the first element of argv to argvarray but the second is not copied. If I pass more than 1 arg it segfaults on strncpy().

Why is this happening? What's the best way to copy all elements of a char array (particularly char arrays declared in function definitions) to other char arrays without knowing the size before hand, as in the case of argv?

user229044
  • 232,980
  • 40
  • 330
  • 338
Jack Galt
  • 83
  • 8
  • 2
    You never allocate memory to which the elements in `argvarray` could point to. – Peter - Reinstate Monica Feb 19 '16 at 13:40
  • 1
    `arrlen` is not initialized. – Andrew Henle Feb 19 '16 at 13:44
  • Thanks guys, I appreciate the assistance, and your patience as I learn. – Jack Galt Feb 19 '16 at 14:20
  • Study arrays and pointers in detail before moving on to string handling. – Lundin Feb 19 '16 at 14:22
  • @Lundin That's exactly what I'm doing, studying arrays and pointers. I'm a 30 year programmer (of a different sort) and I suspect that's actually a detriment to me learning C. But, I learn best through practical use of individual concepts as opposed to volumes of discourse on theory and arbitrary example. Since I primarily work with strings and ints it's imperative that I understand how to apply arrays and pointers to strings and ints. Ergo, the request for assistance in learning how to apply them. – Jack Galt Feb 19 '16 at 14:43

4 Answers4

3
arrlen = arrlen + strlen(argv[j]);

arrlen is used uninitialized (undefined behaviour).

And as pointed out By @PeterA.Schneider, you need room for each element of argvarray, use malloc before strncpy or strdup

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
1

You're confused about arrays vs pointers.

If you declare an array char tab[2][3], it'll be stored contiguously in memory:

[h][e][y][y][o][u] (a simple example).

But here, you have pointers, so char (*tab)[2] is an array of two pointers:

tab = [0x1234][0x5678]
0x1234 = "hey"
0x5678 = "you"

strncpy copies contiguous parts of memory. To copy argv, copy each pointer instead (call malloc + strcpy one for each char* is the easiest option)

(also see @AlterMann's answer, which is correct as well)

Ven
  • 19,015
  • 2
  • 41
  • 61
  • YES! Arrays are kicking my butt. Pointers aren't much better. If I weren't in need of a better understanding of C I'd probably rather spend time juggling knives. I'll get there eventually though (I hope) – Jack Galt Feb 19 '16 at 14:31
1
  1. arrlen is not initialised. You increase its value then attempt to use it as a parameter to strncpy. The program behaviour will be undefined. Write int arrlen = 0; instead.

  2. argvarray is an array of pointers to char. You don't allocate any memory for each element. *argvarray is equivalent to argvarray[0] which is a char* that doesn't point to anything. So, the behaviour of strncpy will be undefined.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

Apart from that variable arrlen was not initialized

int arrlen;

and as result the value of the variable after execution the loop

for(int j=0; j< argc; j++){
    arrlen = arrlen + strlen(argv[j]);
}

will be indeterminate this call

strncpy(*argvarray, *argv, arrlen); 

does not make sense and has undefined behaviour.

I think what you mean is the following

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

int main(int argc, char *argv[])
{
    printf("%d\n", argc);
    char *argvarray[argc];

    for ( int i = 0; i < argc; i++ )
    {
        argvarray[i] = malloc( strlen( argv[i] ) + 1 ); 
        strcpy( argvarray[i], argv[i] );
    }

    for ( int i = 0; i < argc; i++ )
    {
        printf( "value of i: %d\n", i ); //to see what's going on
        printf( "%s\n", argv[i] ); 
        printf( "%s\n", argvarray[i] ); //gets 1st element no problem
    }

    for ( int i = 0; i < argc; i++ ) free( argvarray[i] );

    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thanks a million. I see how the other answers were basically the same as yours, but your example of usage really helped clarify it. Quality answer!! – Jack Galt Feb 19 '16 at 14:17