Problem Outputting Command Line Arguments from argv

M

Matt

Hello. I'm having a very strange problem that I would like ot check
with you guys.

Basically whenever I insert the following line into my programme to
output the arguments being passed to the programme:

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

The porgramme outputs 3 of the command line arguements, then gives a
segmentation fault on the next line, followed by other strange
behaviour.

Does outputting the command line arguments change them or some other
aspect of the programme somehow? The programme runs fine when I
comment the line out, which just makes no sense to me!

Kind Regards,

Matt
 
S

santosh

Hello. I'm having a very strange problem that I would like ot check
with you guys.

Basically whenever I insert the following line into my programme to
output the arguments being passed to the programme:

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

The porgramme outputs 3 of the command line arguements, then gives
a segmentation fault on the next line, followed by other strange
behaviour.

Does outputting the command line arguments change them or some
other aspect of the programme somehow? The programme runs fine when
I comment the line out, which just makes no sense to me!


In C arrays begin at subscript zero and end at subscript N-1, for an
array of N elements. The argv array is an array of char *. The
number of elements in this array is given by the first argument to
main, traditionally called as argc. So when printing out the program
arguments, you must iterate through the argv array from subscript
zero up to and including subscript argc-1. argv[argc] is a null
pointer. Passing a null pointer to most functions that expect a
valid pointer value causes undefined behaviour.
 
K

Keith Thompson

Matt said:
Hello. I'm having a very strange problem that I would like ot check
with you guys.

Basically whenever I insert the following line into my programme to
output the arguments being passed to the programme:

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

The porgramme outputs 3 of the command line arguements, then gives a
segmentation fault on the next line, followed by other strange
behaviour.

Does outputting the command line arguments change them or some other
aspect of the programme somehow? The programme runs fine when I
comment the line out, which just makes no sense to me!


That line looks ok (except that you probably should have the "\n" at
the end of the ouput line and you misspelled "argument", and the '.'
character at the end of the line can cause confusion, but those aren't
relevant to your real problem). In other words, you've shown us
exactly the portion of your code that *isn't* relevant to the problem
you're having.

If I had to guess, I'd say you probably have something like:

for (i = 1; i <= argc; i ++) {
/* your printf call here */
}

On the last iteration of the loop, you attempt to print the value of
argc[argc], which is guaranteed to be a null pointer.

Or the problem might be something else entirely; I'm only guessing.

If you had posted your actual code (copy-and-paste the entire program,
which you've trimmed down to something big enough to exhibit the
problem but small enough to be easy for us to analyze), then I
wouldn't have had to guess.

Just another wild guess: did you remember the required
'#include <stdio.h>'?
 
M

Matt

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, the next time the programme 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
 
F

Flash Gordon

Matt wrote, On 22/07/07 23:45:
The relevant part of my code reads as follows:

How do you know the relevant part if you don't know what the problem is?
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?


Did you actually try running it? If so it would have failed because argv
is a char**, so argv is a char*, so *argv is a char and %s expects
a pointer to a string, not a single character.
Something else that is rather worrying is that if I comment this bit
out, the next time the programme 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.

You have a bug. However, if you do not show your real code no one can
show you your real bug.
 
K

Keith Thompson

Matt said:
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?


Other relevant parts of your code are the declaration of 'main', the
declaration of 'i', and so so forth. In other words, given the code
you posted, it shouldn't be difficult to write and post a complete
program. It probably doesn't make much difference in this case, but
in general posting compilable code makes it a lot easier for us to
help.

In your printf statements, you print a '\n' character at the
*beginning* of each line rather than at the end. That seems to be a
common style for Windows programs (I have no idea why), but it's
generally better to *end* each line with a '\n' character. In
particular, if your last line of output doesn't end with a '\n', bad
things can happen. (It may happen to work on your implementation, but
the fact that you're posting here implies that you're interested in
portable code.)

To answer your actual question, no, you don't want the '*' in
'*argv'. argv is of type char**, a pointer to pointer to char.
argv is of type char*, a pointer to char. And type char* happens
to be exactly what the "%s" format requires. (The char* value needs
to be a pointer to the first character of a string.)
Something else that is rather worrying is that if I comment this bit
out, the next time the programme 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.

Well, we can't guess why your *other* code is failing without seeing
it.

How do you know that argv[0] is not equal to NULL? According to the
standard, argv[0] *must* be a null pointer if argc==0. Even if
argc>0, some implementations still allow argv[0]==NULL under some
circumstances (though this is a violation of the standard's
requirements).

Try checking the value before trying printing what it points to. For
example:

if (argv == NULL) {
printf("argv[%d] = NULL\n", i);
}
else {
printf("argv[%d] = \"%s\"\n", i, argv);
}
 
M

Matt

Matt said:
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?


Other relevant parts of your code are the declaration of 'main', the
declaration of 'i', and so so forth. In other words, given the code
you posted, it shouldn't be difficult to write and post a complete
program. It probably doesn't make much difference in this case, but
in general posting compilable code makes it a lot easier for us to
help.


I wish I could, but sadly the programme in its entirely is huge and is
split up into many different source files. 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...

with the example code:

http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-...

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');

}

}
How do you know that argv[0] is not equal to NULL? According to the
standard, argv[0] *must* be a null pointer if argc==0. Even if
argc>0, some implementations still allow argv[0]==NULL under some
circumstances (though this is a violation of the standard's
requirements).

By changing *argv back to argv, the programme now prints the
value of
argv[0] to the screen, followed by a segmentation fault.
 
P

pete

Matt said:
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, the next time the programme 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.


/* BEGIN new.c */

#include <stdio.h>

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

printf("\narg = %d\n\n", argc);
if (argc > 1) {
for (i = 0; i != argc; ++i) {
printf("Command line arguement %d:%s\n", i, argv);
}
} else {
puts("This program displays command line arguments.");
for (i = 0; *argv != NULL; ++argv) {
printf("Command line arguement %d:%s\n", i, *argv);
}
}
return 0;
}

/* END new.c */
 
K

Keith Thompson

Matt said:
I wish I could, but sadly the programme in its entirely is huge and is
split up into many different source files.

Sure you can.
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...

with the example code:

http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-...

My implemtation is as follows:

for ( i = 0 ; i < argc ; i++ ) [big snip]
}

The code you're having trouble with is accessing argc and argv. Just
narrow it down to something that accesses argc and argv in the same
way, but doesn't call anything non-standard (for example, anything
that refers to getopt), while still exhibiting the same problem. Make
sure the resulting program compiles and links; it needs to include a
declaration of main, for example.

Quite possibly you'll figure out the problem while doing this. If
not, post it and we can help you.
 
M

Matt

Quite possibly you'll figure out the problem while doing this. If
not, post it and we can help you.

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
 
M

Matt

Having made a test programme as follows for printing argc and argv to
the screen:

"// 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
 
M

Matt

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
 
K

Keith Thompson

Matt said:
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.

I'm a little surprised it didn't compile, but using '-c' is nonsense.
Multi-character character constants have implementation-defined
values, and should be avoided. '-c' and "-c" are entirely different
things.

I think a large part of the problem is that you're trying to program
by wild guessing. You need to understand what you're doing *before*
you write or modify your code. Making random changes will most likely
cause your code to fail to compile. If by chance it still compiles,
it probably won't work. If by chance it appears to work, that's
probably just bad luck; it's *very* easy in C to write incorrect code
that happens to "work" because you got lucky with undefined behavior.

Correctly working C code is a very small target, tightly surrounded by
code that's incorrect in various subtle ways. The only way to hit the
target is to know where it is and aim at it directly.

Study your text book (K&R2 is good), decide what you want to do,
figure out how to do it, and do it.
 
O

Old Wolf

char *getopt_val;
[...]
if (getopt_val == -1)

This is an error. If you did not get a compiler
warning or error here, then you need to learn
how to invoke your compiler properly.

I can't suggest what the 'correct' code would
be, because you haven't posted any of the
code for 'getopt_long'. Perhaps you would get
better answers by posting your program on a
newsgroup where 'getopt_long' is topical
(possibly a GCC group or a Unix programming group).
switch (*getopt_val)

You should check that getopt_val is not NULL
before doing this.

Also, don't put too much stock in any debugger
report that one particular piece of code is the
problem, they often get it wrong, especially if
you haven't compiled your code to disable optimizations.
printf ("option %s", long_options[option_index].name);

if (optarg)

You haven't declared 'optarg' anywhere, as far as I can see.
 
B

Barry Schwarz

Having made a test programme as follows for printing argc and argv to
the screen:

"// 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>

None of these preprocessor directives do any loading nor do they have
anything to do with libraries as the word is commonly used.
// 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]);

Why do you want to print the same string umpteen times?
}

}"

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.

No it is not. It is the quantity of char* that you can find via argv.
The first such char* is usually points to the command used to execute
the program.
{

// 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


What makes you think argv[i+1] exists and is not NULL?
// 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.

Only for a strange definition of flawlessly.


Remove del for email
 
B

Barry Schwarz

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;

Other than hiding the previous object with this name, what do you
think this accomplishes?
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)


getopt_val was defined above as a char*. -1 is an int. You cannot
compare an int to a pointer this way. What is the real return type of
getopt_long? This statement is a constraint violation that requires a
diagnostic.
{

break;

}

switch (*getopt_val)

{

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

{

Judicious use of white space makes your code readable. Double spacing
nearly every statement doesn't qualify.
break;

}

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

if (optarg)

What is 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)

What is optind?
{

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.

It still doesn't.


Remove del for email
 
M

Matt

I have tried replacing "case 'c':" with "case '-c':" and so forth in
I'm a little surprised it didn't compile, but using '-c' is nonsense.
Multi-character character constants have implementation-defined
values, and should be avoided. '-c' and "-c" are entirely different
things.

Good point. Ta for the advice as well.
 
K

Keith Thompson

Matt said:
Good point. Ta for the advice as well.

I wrote the paragraph starting with "I'm a little surprised it didn't
compile ...".

Once again, please stop snipping attribution lines. You can see a
There was a similar line above what I wrote in your followup, but you
deleted it. Delete whatever quoted material isn't relevant to your
followup, but if you quote anything by an author, *leave the
attribution line in place*.

Not only is it simply polite to give credit (or blame) for anything
that you quote, it makes the conversation easier to follow.
 
M

Matt

I wrote the paragraph starting with "I'm a little surprised it didn't
compile ...".

Once again, please stop snipping attribution lines. You can see a
There was a similar line above what I wrote in your followup, but you
deleted it. Delete whatever quoted material isn't relevant to your
followup, but if you quote anything by an author, *leave the
attribution line in place*.

Not only is it simply polite to give credit (or blame) for anything
that you quote, it makes the conversation easier to follow.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <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"

No problem
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top