PDA

View Full Version : Segmentation fault - getopt_long()



capslocktrojan
10-24-2014, 03:56 PM
Hello friends

I am trying to implement command line options in a C Program. Please refer to the code below.



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

struct option longopts[] = {
{"help", no_argument, 0, 'h'},
{"open", required_argument, 0, 'o'}
};

void usage(FILE *file);

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

int i, ch, indexptr = 0;
opterr = 0;

while ((ch = getopt_long(argc, argv, "ho:", longopts, &indexptr)) != -1) {
switch(ch) {
case 'h':
usage(stdout);
exit(0);
break;
case 'o':
printf("Optarg file will be opened here\n");
break;
default:
printf("Didn't recognize that option. Try again\n");
exit(0);
}
}

argc -= optind;
argv += optind;

if(argc == 0){
fprintf(stderr,"ERROR: Required arguments missing. Please refer to the usage below: \n");
usage(stderr);
exit(1);
}

return 0;
}

void usage(FILE *file) {
if(file == NULL){
file = stdout;
}

fprintf(file,
"./program [OPTIONS] file.txt\n"
" --help \t Print this help screen\n"
" --open \t Open a file\n");
}


When I compile it and run,
for

./program --help
it's not generating any errors.

But for

./program --he
it's generating Segmentation fault. It is throwing up this error for --h, --he, --hel etc.,

Also, when I give, --open as the option, it's not even recognizing this.

I took a look at the manual of getopts_long but couldn't identify the problem.

Can somebody point out the mistake?

Thanks in advance.

grumpy
10-24-2014, 04:08 PM
This is not a C problem. getopt_long() is linux specific. Try asking your question in a linux programming forum.

laserlight
10-24-2014, 10:54 PM
*moved to Linux programming*

phantomotap
10-24-2014, 11:15 PM
O_o

You must correctly use the `getopt_long' interface.

Specifically, you aren't providing a valid `longopts' pointer.

You should read some more examples.

Soma

Salem
10-24-2014, 11:23 PM
It all looks fine here.


$ gcc -g bar.c
$ ./a.out --hel
./program [OPTIONS] file.txt
--help Print this help screen
--open Open a file
$ ./a.out --he
./program [OPTIONS] file.txt
--help Print this help screen
--open Open a file
$ ./a.out -h
./program [OPTIONS] file.txt
--help Print this help screen
--open Open a file


I used -g to add symbols to the executable, in the expectation of having to use gdb.

capslocktrojan
10-25-2014, 08:45 AM
Hi Salem

Thanks for your input.

Did you try ./a.out -o or ./a.out --open?



It all looks fine here.


$ gcc -g bar.c
$ ./a.out --hel
./program [OPTIONS] file.txt
--help Print this help screen
--open Open a file
$ ./a.out --he
./program [OPTIONS] file.txt
--help Print this help screen
--open Open a file
$ ./a.out -h
./program [OPTIONS] file.txt
--help Print this help screen
--open Open a file


I used -g to add symbols to the executable, in the expectation of having to use gdb.

capslocktrojan
10-25-2014, 08:47 AM
Hi Soma

Can you point me to some good examples?

I've been searching and reading things, but I don't feel they are complete.

Apologies if I'm missing something.

Thanks

O_o

You must correctly use the `getopt_long' interface.

Specifically, you aren't providing a valid `longopts' pointer.

You should read some more examples.

Soma

Nominal Animal
10-25-2014, 09:36 AM
getopt_long() is linux specific.
No, it was originally a GNU C library extension, but nowadays implemented on BSDs, including e.g. Macs (https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/getopt_long.3.html).

It's a pity there is no GNU or POSIX C or "non-Windows" forum, since questions pertaining to those are so readily shunted to the "Linux programming" sub-forum, while Linux is just one environment those are available. (Might be one reason why there are so few non-Windows, non-Linux programmers here, just an occasional microcontroller person.)



struct option longopts[] = {
{"help", no_argument, 0, 'h'},
{"open", required_argument, 0, 'o'}
};

The array of options should end with a terminating entry (typically, NULL or all zeroes). Without it, getopt_long() (http://man7.org/linux/man-pages/man3/getopt_long.3.html) will try to access past the end of the array.

(Some functions take both a pointer and a length; those arrays do not need a terminator entry. Other functions, like getopt_long(), take just the array (or the pointer to the first entry in the array); that's a clear indicator you do need the terminating entry.)

Salem used a different compiler or compiler options, that happens to generate a long enough run of zeros after that array -- just as if you had added the terminating entry.

In other words:

struct option longopts[] = {
{"help", no_argument, 0, 'h'},
{"open", required_argument, 0, 'o'},
{0}
};

A good example is available at the Linux man-pages project (https://www.kernel.org/doc/man-pages/), getopt_long(3) (http://man7.org/linux/man-pages/man3/getopt_long.3.html) man page, near the bottom of the page. (The project name refers to man pages that are relevant to all Linux applications, not man pages defined by Linux folks.) Each page has a Conforming to section you can check to see when and where the function is available.