-1

I am taking command line argument which I am copying to my character pointer. but its giving me an error.

int main(int argc, char *argv[])
{
    char *cmdarg;
    if(argc>1)
            strcpy(cmdarg, argv[1]);
    else
            cmdarg = NULL;
    return 0;
}

This gives me

Segmentation fault (core dumped)
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • `cmdarg` is uninitialised. Did you not get a compiler warning? If not, turn them on. – fredrik Feb 15 '20 at 09:02
  • How do I turn it on? `char *cmdarg="sample"` its still not working –  Feb 15 '20 at 09:05
  • A pointer holds the address to a valid block of memory where something else is/can be stored. What valid block of memory does `cmdarg` hold the address to as its value? (i.e. what block of memory does it point to?) – David C. Rankin Feb 15 '20 at 09:07
  • so that means you cannot use stcpy with a char pointer? –  Feb 15 '20 at 09:08
  • You need to allocate the memory using `malloc` or a similair function. Don't forget to free it when you're done. – fredrik Feb 15 '20 at 09:09
  • `char *cmdarg="sample"` creates the *String-Literal* `"sample"` and assigns the beginning address of the string to `cmdarg`. However, on all conforming systems a String-Literal is created in read-only memory and cannot be modified. (windows is the outlier) – David C. Rankin Feb 15 '20 at 09:10
  • guyz I got confused while reading books I show `cmdarg = argv[1]`. I forgot the point that strcpy copies character by character and a string literal is read only and we cannot change it. Hence ignoring these facts I tried strcpy instead of assignment operator –  Feb 15 '20 at 09:15

2 Answers2

2

You did not allocate memory where you are going to copy the argument pointed to by the expression argv[1].

Try the following

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

int main(int argc, char *argv[])
{
    char *cmdarg = NULL;

    if( argc > 1 )
    {
        cmdarg = malloc( strlen( argv[1] ) + 1 );
        if ( cmdarg != NULL ) strcpy( cmdarg, argv[1] );
    }

    // ...    Some other code

    free( cmdarg );

    return 0;
}

If you want just to store the value of the pointer argv[1] then write

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

int main(int argc, char *argv[])
{
    char *cmdarg = NULL;

    if( argc > 1 )
    {
        cmdarg = argv[1];
    }

    // ...    Some other code

    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I kinda liked the two `PP`s in Pointer -- really emphasized the Point `:)` – David C. Rankin Feb 15 '20 at 09:11
  • No No wait I got confused while reading bookswhich mentioned `cmdarg = argv[1]`. I forgot the point that strcpy copies character by character and a string literal is read only and we cannot change it. Hence ignoring these facts I tried strcpy instead of assignment operator –  Feb 15 '20 at 09:15
  • Glad you found it, you can assign `cmdarg = argv[1];` and now `cmdarg` holds the address of `argv[1]` as its value and you can use the pointer just as you would `argv[1]` itself. – David C. Rankin Feb 15 '20 at 09:17
  • Why in the world are you not just doing `strdup()` rather than the `malloc()` and `strcpy()` pair? – Kurtis Rader Feb 16 '20 at 03:54
  • @KurtisRader strdup is not a standard function. – Vlad from Moscow Feb 16 '20 at 11:06
  • @VladfromMoscow `strdup()` is a standard function. It was recently added to the ISO C standard and I've never encountered a system without it. I've been programming on UNIX based systems since 1985. Regardless, using `strcpy()` is silly since you've already determined the length of the string. It would be more efficient to use `memcpy()`. – Kurtis Rader Feb 17 '20 at 02:23
  • @KurtisRader When was it included in the C Standard? I have no such an information. In the C Draft 202x there is no strdup. – Vlad from Moscow Feb 17 '20 at 10:10
1

cmdarg is a Uninitialized pointer by declaration. We have to allocate dynamic memory for cmdarg to point to. Below is a sample code

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

int main(int argc, char *argv[])
{
    char *cmdarg;

    cmdarg = malloc( 5 * sizeof(char));
    if(argc>1)
    {
            strcpy(cmdarg, argv[1]);
            printf("%s\n", cmdarg);
    }
    else
            cmdarg = NULL;
    free(cmdarg);
    return 0;
}

Output while running with argument ./a.out yes is yes.

Note: Size allocated should not be lesser while using strcpy(). Make sure to use strncpy()

  • Hmmm... *"junk pointer"*, I'm not sure I've stumbled across that in the C Standard yet. Perhaps you mean an *"Uninitialized Pointer"* that points nowhere. Also, `sizeof(char)` is defined as `1` so it need no be included in `malloc( 5 * sizeof(char));`, better `malloc (strlen(argv[1]) + 1);` – David C. Rankin Feb 15 '20 at 09:15
  • 1
    No No wait I got confused while reading books which mentioned `cmdarg = argv[1]`. I forgot the point that strcpy copies character by character and a string literal is read only and we cannot change it. Hence ignoring these facts I tried strcpy instead of assignment operator –  Feb 15 '20 at 09:15
  • 1
    You can use direct assignment cmdarg = argv[1]. Since arguments get stored in stack/ register based on the compiler. This statement cause cmdarg to point to the starting location of argv[1]. – Sadaananth Anbucheliyan Feb 15 '20 at 09:28
  • Yeah @David I meant Uninitialized pointer. I will edit in the answer too. Uninitialized pointer is nothing but an another memory location that can hold address of other memory location. Since it is local variable pointer, It will have a junk value which points to some other location we don't care. So It is good habit initialize a pointer after declaration – Sadaananth Anbucheliyan Feb 15 '20 at 09:31
  • Good job, I knew what you meant, but it's better to provide an answer to someone learning that provides the correct nomenclature for the problem, rather than an accurate metaphor `:p` – David C. Rankin Feb 15 '20 at 10:44