Strange Error after printing argv values

Discussion in 'C Programming' started by Matt, Jul 19, 2007.

  1. Matt

    Matt Guest

    Hello. I've got a very strange problem. Basically I have a programme
    where I wish to view all the strings in the argv array so I can see
    what arguments are being passed to the programme.

    However, when I insert the following line at the start of a FOR loop
    early on the in the programme to do this:

    printf("\nCommand line arguement %d: %s. \n", i , argv );

    I get back the first 3, then I get a segmentation fault followed by
    all kinds of errors. When I comment this line out he programme runs
    with no problems.

    It seems that reading and outputting the values of argv is changing
    something in the programme. How can just outputting the values of argv
    to the screen cause this?

    Kind Regards,

    Matt
     
    Matt, Jul 19, 2007
    #1
    1. Advertising

  2. In article <>,
    Matt <> wrote:
    >Hello. I've got a very strange problem. Basically I have a programme
    >where I wish to view all the strings in the argv array so I can see
    >what arguments are being passed to the programme.
    >
    >However, when I insert the following line at the start of a FOR loop
    >early on the in the programme to do this:
    >
    >printf("\nCommand line arguement %d: %s. \n", i , argv );


    I assume that you did:

    for (i=1; i<=3; i++)
    printf("\nCommand line arguement %d: %s. \n", i , argv );

    When you should have done:

    for (i=0; i<argc; i++)
    printf("\nCommand line argument %d: %s. \n", i , argv );
     
    Kenny McCormack, Jul 19, 2007
    #2
    1. Advertising

  3. Matt

    Guest

    Maybe you're trying to print too many? The loop should be
    for (i = 0; i < argc; ++i) { ... }
    For example, in the call
    myprogram 1776.0 xyzzy
    argc will be 3. argv[0] will be myprogram, argv[1] will be 1776.0,
    and argv[2] will be xyzzy.
     
    , Jul 19, 2007
    #3
  4. Matt

    Old Wolf Guest

    (Kenny McCormack) wrote:
    >
    > When you should have done:
    >
    > for (i=0; i<argc; i++)
    > printf("\nCommand line argument %d: %s. \n", i , argv );


    The arguments can still be NULL; in particular,
    argv[0] could be null. This happens even on the
    most common OS's; e.g. when a task is invoked via
    a call like execv where the caller specifies the
    arguments, including argv[0].

    So you should write:

    for (i=0; i<argc; i++)
    if ( argv )
    printf("Command line argument %d: %s.\n", i , argv );

    or perhaps :

    for (i=0; i<argc; i++)
    printf("Command line argument %d: %s.\n",
    i , argv ? argv : "<null>");
     
    Old Wolf, Jul 20, 2007
    #4
  5. Matt

    Al Balmer Guest

    On Thu, 19 Jul 2007 14:08:26 -0000, Matt <> wrote:

    >Hello. I've got a very strange problem. Basically I have a programme
    >where I wish to view all the strings in the argv array so I can see
    >what arguments are being passed to the programme.
    >
    >However, when I insert the following line at the start of a FOR loop
    >early on the in the programme to do this:
    >
    >printf("\nCommand line arguement %d: %s. \n", i , argv );
    >
    >I get back the first 3, then I get a segmentation fault followed by
    >all kinds of errors. When I comment this line out he programme runs
    >with no problems.
    >
    >It seems that reading and outputting the values of argv is changing
    >something in the programme. How can just outputting the values of argv
    >to the screen cause this?
    >

    It can't. However, fetching the argv can certainly cause a
    segfault, if i is greater than or equal to the number of arguments you
    actually have. I would guess that you're invoking the program with two
    or less arguments (argv[0]) will be the name in most cases, but not
    guaranteed.) The typical name for the count variable is argc. A
    typical program will be something like

    #include <stdio.h>

    int main(int argc, char *argv[])
    {
    ..
    ..
    ..
    int i;
    for (i = 0; i < argc; ++i)
    {
    /* do something with argv, such as: */
    printf("\nCommand line argument %d: '%s'. \n", i , argv );
    }
    ..
    ..
    ..
    }

    --
    Al Balmer
    Sun City, AZ
     
    Al Balmer, Jul 20, 2007
    #5
  6. On Jul 19, 7:32 pm, Old Wolf <> wrote:
    > (Kenny McCormack) wrote:
    >
    > > When you should have done:

    >
    > > for (i=0; i<argc; i++)
    > > printf("\nCommand line argument %d: %s. \n", i , argv );

    >
    > The arguments can still be NULL; in particular,
    > argv[0] could be null. This happens even on the
    > most common OS's; e.g. when a task is invoked via
    > a call like execv where the caller specifies the
    > arguments, including argv[0].


    While this is certainly true it breaks conformity with Standard C
    (except when argc is 0). It is certainly not bad practice to write
    code to anticipate such possibilities but if the values of the program
    parameters are coerced in such a way one should expect to suffer the
    consequences.

    Robert Gamble
     
    Robert Gamble, Jul 20, 2007
    #6
  7. Matt

    Matt Guest

    The relevant part of my code reads as follows:

    for ( i = 0 ; i < argc ; i++ )

    {

    printf("\narg = %d\n" , argc );

    printf("\nCommand line arguement %d: %s. \n", i , *argv );

    and the stdio.h header is loaded at the start. You may notice I have
    added a * before the argv as I realised I wished to print the value
    the pointer points at, was this a correct thing to do?

    Something else that is rather worrying is that if I comment this bit
    out, later in the programme when it tries to read argv[1], I get
    another segmentation fault. I assume this only happens when argv[1] =
    NULL, but since I am almost certain the programme to supplied with at
    least one argument, and that the error occurs when I try to print
    argv[0] (which is the one thing that cannot be NULL!), something else
    must be wrong here.

    Kind Regards,

    Matt
     
    Matt, Jul 22, 2007
    #7
  8. Matt

    Matt Guest

    > I assume that you did:
    >
    > for (i=1; i<=3; i++)
    > printf("\nCommand line arguement %d: %s. \n", i , argv );
    >
    > When you should have done:
    >
    > for (i=0; i<argc; i++)
    > printf("\nCommand line argument %d: %s. \n", i , argv );


    The latter is what I did, as shown in my previous post.
     
    Matt, Jul 22, 2007
    #8
  9. Matt

    Old Wolf Guest

    On Jul 23, 10:48 am, Matt <> wrote:
    > The relevant part of my code reads as follows:
    >
    > printf("\nCommand line arguement %d: %s. \n", i , *argv );
    >
    > and the stdio.h header is loaded at the start. You may notice I have
    > added a * before the argv as I realised I wished to print the value
    > the pointer points at, was this a correct thing to do?


    No. Read the documentation for printf, specifically
    %s. You will see that it expects a pointer to char.
    This is because the printf function has to be able
    to increase the pointer until it reaches the end-
    of-string marker.

    As it stands, your code causes undefined behaviour
    because you did not pass a pointer-to-char for
    %s, so anything could happen. A segfault is most
    likely; garbage output is another possibility.

    > Something else that is rather worrying is that if I comment this bit
    > out, later in the programme when it tries to read argv[1], I get
    > another segmentation fault.


    Post the exact program that causes the fault.

    > I assume this only happens when argv[1] = NULL


    Why assume? Add in code to check if this is happening.
     
    Old Wolf, Jul 22, 2007
    #9
  10. Matt

    Matt Guest

    > No. Read the documentation for printf, specifically
    > %s. You will see that it expects a pointer to char.
    > This is because the printf function has to be able
    > to increase the pointer until it reaches the end-
    > of-string marker.
    >
    > As it stands, your code causes undefined behaviour
    > because you did not pass a pointer-to-char for
    > %s, so anything could happen. A segfault is most
    > likely; garbage output is another possibility.


    Just before your reply I got rid of the *, and now I get the value of
    argv[0] printed to the screen, followed by a segmentation fault.

    > > Something else that is rather worrying is that if I comment this bit
    > > out, later in the programme when it tries to read argv[1], I get
    > > another segmentation fault.

    >
    > Post the exact program that causes the fault.


    The programme in its entirity is far too large I'm afraid. Basically
    the bit of troublesome code arises from my implementation of the
    getopt_long function from the GNU library:

    http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html#Getopt-Long-Options

    with the example code:

    http://www.gnu.org/software/libc/ma...ption-Example.html#Getopt-Long-Option-Example

    My implemtation is as follows:

    for ( i = 0 ; i < argc ; i++ )

    {

    printf("\nargc = %d\n" , argc );

    printf("\nCommand line arguement %d: %s. \n", i , argv );

    while (1)

    {

    static struct option long_options[] =

    {

    // These options set a flag.
    {"stack" , no_argument , &stack_mode , 1}, // Enable
    stack (convolution) mode

    // These options don't set a flag. We distinguish them
    by their indices.
    {"configfile" , required_argument , 0 , 'c'},
    {0 , 0 , 0 , 0}

    };

    // getopt_long stores the option index here.
    int option_index = 0;

    *getopt_val = getopt_long (argc, argv, "c:", long_options,
    &option_index);

    // Detect the end of the options.
    if (*getopt_val == -1)

    {

    break;

    }

    switch (*getopt_val)

    {

    case 0:
    // If this option set a flag, do nothing else now.
    if ( long_options[option_index].flag != 0)

    {

    break;

    }

    printf ("option %s", long_options[option_index].name);

    if (optarg)

    {

    printf (" with arg %s", optarg);

    }

    printf ("\n");
    break;

    case 'c':
    printf ("option -c with value `%s'\n", optarg);
    break;

    case '?':
    /* getopt_long already printed an error message. */
    break;

    default:
    abort ();

    }

    }

    /* Print any remaining command line arguments (not options). */
    if (optind < argc)

    {

    printf ("non-option ARGV-elements: ");

    while (optind < argc)

    {

    printf ("%s ", argv[optind++]);

    }

    putchar ('\n');

    }

    }


    >
    > > I assume this only happens when argv[1] = NULL

    >
    > Why assume? Add in code to check if this is happening.


    Good point. I have checked and argv[1] = NULL.
     
    Matt, Jul 23, 2007
    #10
  11. Matt wrote:
    > The relevant part of my code reads as follows:
    >
    > for ( i = 0 ; i < argc ; i++ )
    >
    > {
    >
    > printf("\narg = %d\n" , argc );
    >
    > printf("\nCommand line arguement %d: %s. \n", i , *argv );
    >
    > and the stdio.h header is loaded at the start. You may notice I have
    > added a * before the argv as I realised I wished to print the value
    > the pointer points at, was this a correct thing to do?


    Almost certainly not. Check the following code. It may contain clues
    to the solution to your problem. Or not. It's hard to tell from your
    statement what it is you really want.

    #include <stdio.h>

    int main(int argc, char *argv[])
    {
    size_t i;
    printf("arg = %d\n", argc);
    for (i = 0; i < (size_t) argc; i++) {
    if (argv)
    printf("Command line argument %zu @ %p = \"%s\".\n", i,
    (void *) argv, argv);
    else
    printf("Command line argument %zu @ %p (null pointer).\n", i,
    (void *) argv);
    }
    return 0;
    }


    $a foo bar lisp green
    arg = 5
    Command line argument 0 @ 939d0 = "./a.exe".
    Command line argument 1 @ 93a00 = "foo".
    Command line argument 2 @ 93a30 = "bar".
    Command line argument 3 @ 93a60 = "lisp".
    Command line argument 4 @ 93a90 = "green".

    >
    > Something else that is rather worrying is that if I comment this bit
    > out, later in the programme when it tries to read argv[1], I get
    > another segmentation fault. I assume this only happens when argv[1] =
    > NULL, but since I am almost certain the programme to supplied with at
    > least one argument, and that the error occurs when I try to print
    > argv[0] (which is the one thing that cannot be NULL!), something else
    > must be wrong here.


    Something is wrong, but unless our crystal balls produce your code, no
    one can even guess what errors you have made.
     
    Martin Ambuhl, Jul 23, 2007
    #11
  12. Matt <> writes:

    > The programme in its entirity is far too large I'm afraid.


    But you will probably solve the problems your self as you try to cut
    it down to a minimal test case that fails. You will either find the
    error or remain baffled with a small test program you *can* post.

    > Basically
    > the bit of troublesome code arises from my implementation of the
    > getopt_long function from the GNU library:
    >
    > http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html#Getopt-Long-Options
    >
    > with the example code:
    >
    > http://www.gnu.org/software/libc/ma...ption-Example.html#Getopt-Long-Option-Example
    >
    > My implemtation is as follows:
    >
    > for ( i = 0 ; i < argc ; i++ )
    >
    > {
    >
    > printf("\nargc = %d\n" , argc );
    >
    > printf("\nCommand line arguement %d: %s. \n", i , argv );
    >
    > while (1)
    >
    > {
    >
    > static struct option long_options[] =
    >
    > {
    >
    > // These options set a flag.
    > {"stack" , no_argument , &stack_mode , 1}, // Enable
    > stack (convolution) mode
    >
    > // These options don't set a flag. We distinguish them
    > by their indices.
    > {"configfile" , required_argument , 0 , 'c'},
    > {0 , 0 , 0 , 0}
    >
    > };
    >
    > // getopt_long stores the option index here.
    > int option_index = 0;
    >
    > *getopt_val = getopt_long (argc, argv, "c:", long_options,
    > &option_index);


    This looks very suspicious but how can we tell? What is getopt_val?
    It it really a pointer to int, and does it point to a modifiable int
    object? At the very least we'd need the declaration and the code that
    might affect it's value from declaration to this point.

    Post a small test program. Making one will teach you far more than
    all the replies you might get here put together.

    --
    Ben.
     
    Ben Bacarisse, Jul 23, 2007
    #12
  13. Matt

    Matt Guest

    > Post a small test program. Making one will teach you far more than
    > all the replies you might get here put together.


    I'll give that a go.

    In the meantime, DDD now reports that with my present code, the
    segmentation fault occurs when I call the getopt_long function in the
    above code:

    "*getopt_val = getopt_long (argc, argv, "c:", long_options,
    &option_index);"

    Is this another example of where I shouldn't have used a *?

    Kind Regards,

    Matt
     
    Matt, Jul 23, 2007
    #13
  14. Matt

    Matt Guest

    On Jul 23, 10:32 am, Matt <> wrote:
    > > Post a small test program. Making one will teach you far more than
    > > all the replies you might get here put together.

    >


    Having made a test programme as follows:

    "// A programme to test argc and argv

    // Load function libraries

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

    // Main function

    int main(int argc , char **argv)

    {

    int i; // DO loop index

    // Print out argc and argv to screen

    for ( i = 0 ; i < argc ; i++ )

    {

    printf("argc = %d\n",argc);
    printf("argv[0] = %s\n",argv[0]);

    }

    }"

    I had no errors, so calling the functions themselves doesn't seem the
    be the problem.

    I have since gone and commented out the getopt_long code I had added
    and reintroduced the original code I had to read in the arguments:

    " for ( i = 0 ; i < argc ; i++ ) // argc is the number of commmand
    line arguements passed to the programme.

    {

    // Compare first two characters from command line arguement. If
    they match, return 0 and execute statement.
    if (!( strncmp( argv , "-c" , 2 )))

    {

    sprintf( config_file , "%s" , argv[ i+1 ] ); // Point programme
    to a new config file by changing the
    // config_file string to the argument following "-c".

    }"

    Interestingly, the programme now works flawlessly as it did before,
    which clearly indicates the code I posted earlier for the getopt_long
    code is the cause of my errors. I will endeavour to produce another
    test programme to try and replicate the segmentation fault and post
    back later.

    Thanks for all the excellent responses so far.

    Kind Regards,

    Matt
     
    Matt, Jul 23, 2007
    #14
  15. Matt

    Matt Guest

    I have just tried running the code given from the GNU Example page,
    and as I should have expected, the code was fine.

    Now when I put my own implementation of this code (which is of course
    very similar) by itself, I got a segmentation fault whenever I put in
    an argument such as "-c" or "-stack" that the programme is meant to
    recognise and act upon. The problem does not occur if I use "c" or
    "stack":

    // A programme to test my implementation of the getopt_long function
    in an independant environment from the main programme

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

    static int stack_mode = 0;

    int main( int argc , char *argv[] )

    {

    extern int stack_mode;

    char *getopt_val;
    int i;

    opterr = 0;

    printf("argc = %d\n",argc);

    for ( i = 0 ; i < argc ; i++ )

    {

    printf("argv[%d] = %s\n",i,argv);

    }

    for ( i = 0 ; i < argc ; i++ ) // argc is the number of command line
    arguments passed to the programme.

    {

    while (1)

    {

    static struct option long_options[] =

    {

    // These options set a flag.
    {"stack" , no_argument , &stack_mode , 1}, // Enable stack
    (convolution) mode

    // These options don't set a flag. We distinguish them
    by their indices.
    {"configfile" , required_argument , 0 , 'c'},
    {0 , 0 , 0 , 0}

    };

    // getopt_long stores the option index here.
    int option_index = 0;

    getopt_val = getopt_long (argc, argv, "c:", long_options,
    &option_index);

    // Detect the end of the options.
    if (getopt_val == -1)

    {

    break;

    }

    switch (*getopt_val)

    {

    case 0:
    /* If this option set a flag, do nothing else now. */
    if ( long_options[option_index].flag != 0)

    {

    break;

    }

    printf ("option %s", long_options[option_index].name);

    if (optarg)

    {

    printf (" with arg %s", optarg);

    }

    printf ("\n");
    break;

    case 'c':
    printf ("option -c with value `%s'\n", optarg);
    break;

    case '?':
    /* getopt_long already printed an error message. */
    break;

    default:
    abort ();

    }

    }

    /* Print any remaining command line arguments (not options). */
    if (optind < argc)

    {

    printf ("non-option ARGV-elements: ");

    while (optind < argc)

    {

    printf ("%s ", argv[optind++]);

    }

    putchar ('\n');

    }

    }

    }

    I have tried replacing "case 'c':" with "case '-c':" and so forth in
    the case statements starting on line 92, but the source code would not
    compile.

    Kind Regards,

    Matt
     
    Matt, Jul 23, 2007
    #15
  16. Matt

    Matt Guest

    Forgot to mention, the code above should compile so feel free to give
    it a try.
     
    Matt, Jul 23, 2007
    #16
  17. Matt <> writes:

    >> Post a small test program. Making one will teach you far more than
    >> all the replies you might get here put together.

    >
    > I'll give that a go.
    >
    > In the meantime, DDD now reports that with my present code, the
    > segmentation fault occurs when I call the getopt_long function in the
    > above code:
    >
    > "*getopt_val = getopt_long (argc, argv, "c:", long_options,
    > &option_index);"
    >
    > Is this another example of where I shouldn't have used a *?


    How could anyone tell? At the very least, show us the variable's
    declaration and everywhere it is set.

    You can't learn to program in C by added and removing * to see what
    works. One you program will work and you will be happy. Lots of
    programs "work" (i.e. behave as expected), with certain test cases
    compiled with a particular compiler, on one particular system.

    --
    Ben.
     
    Ben Bacarisse, Jul 23, 2007
    #17
  18. Matt <> writes:

    > I have just tried running the code given from the GNU Example page,
    > and as I should have expected, the code was fine.
    >
    > Now when I put my own implementation of this code (which is of course
    > very similar) by itself, I got a segmentation fault whenever I put in
    > an argument such as "-c" or "-stack" that the programme is meant to
    > recognise and act upon. The problem does not occur if I use "c" or
    > "stack":


    Excellent -- a program we can read from top to bottom.

    > char *getopt_val;

    ....
    > getopt_val = getopt_long (argc, argv, "c:", long_options,
    > &option_index);


    A problem. getopt_long (OK not topical, but the error is) returns an
    it. getopt_val should be a "int" not a "char *".

    > switch (*getopt_val)


    Boom! getopt_val does not point to an object so * of it causes
    undefined behaviour.

    Look at the declarations for any functions you use, and (by and large)
    you will save any results returned in variables of that type.

    --
    Ben.
     
    Ben Bacarisse, Jul 23, 2007
    #18
  19. Matt <> writes:
    >> Post a small test program. Making one will teach you far more than
    >> all the replies you might get here put together.

    >
    > I'll give that a go.

    [snip]

    Please don't snip attribution lines. Quoting someone else's writing
    without credit is considered rude.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jul 23, 2007
    #19
  20. Matt <> writes:
    [...]
    > // Print out argc and argv to screen
    >
    > for ( i = 0 ; i < argc ; i++ )
    >
    > {
    >
    > printf("argc = %d\n",argc);
    > printf("argv[0] = %s\n",argv[0]);
    >
    > }

    [...]

    The value of argc is a single number that doesn't change; why do you
    print it inside the loop?

    On each iteration of the loop, you print the value of argv[0]. You
    almost certainly want to print argv.

    Take a look at this. It's not intended to solve your problem, just to
    demonstrate how to deal with argc and argv. Checking each argument
    against NULL is perhaps overkill, but it's better to be too cautious
    than not cautious enough.

    #include <stdio.h>
    int main(int argc, char **argv)
    {
    int i;
    printf("argc = %d\n", argc);
    for (i = 0; i < argc; i ++) {
    if (argv == NULL) {
    printf("argv[%d] = NULL\n", i);
    }
    else {
    printf("argv[%d] = \"%s\"\n", i, argv);
    }
    }
    return 0;
    }

    Also, please don't use "//" comments when posting to Usenet. They're
    not supported in C90 (though many compilers support them as an
    optional extension), and they can cause problems with line wrapping.
    If Usenet software somewhere splits a "//" comment across two lines,
    it creates a syntax error. If a "/* ... */" comment is split, it's
    generally not a problem. And keep your lines short, no more than 72
    columns.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jul 23, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bret

    char **argv vs. char* argv[]

    Bret, Aug 31, 2003, in forum: C Programming
    Replies:
    21
    Views:
    4,635
    Richard Heathfield
    Sep 3, 2003
  2. David
    Replies:
    10
    Views:
    6,013
    Richard Heathfield
    Sep 15, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,686
    Old Wolf
    Jan 20, 2004
  4. =?ISO-8859-1?Q?Thomas_N=FCcker?=

    sys.argv[0] - 'module' object has no attribute 'argv'

    =?ISO-8859-1?Q?Thomas_N=FCcker?=, Jun 30, 2003, in forum: Python
    Replies:
    0
    Views:
    944
    =?ISO-8859-1?Q?Thomas_N=FCcker?=
    Jun 30, 2003
  5. jab3

    char **argv & char *argv[]

    jab3, Dec 4, 2004, in forum: C Programming
    Replies:
    5
    Views:
    682
    Chris Torek
    Dec 8, 2004
Loading...

Share This Page