Home > Mobile >  Comparing chars from command line arguments in C
Comparing chars from command line arguments in C

Time:09-14

I am trying to compare options that can be entered on the command line for my program. for option f a user can enter c or b.

int main(int argc, char** argv){
    char *i;
    char *o;
    char *f;
    int c;
    while ((c = getopt (argc, argv, "i:o:f")) != -1)
        switch (c)
        {
            case 'i':
              i = optarg;
              break;
            case 'o':
              o = optarg;
              break;
            case 'f':
              f = optarg;
              break;
        }
    if(strcmp(f, "b") == 0){
        //execute code
    }
}

When I run this I get the following error:

Program received signal SIGSEGV, Segmentation fault.

__strcmp_avx2 () at ../sysdeps/x86_64/multiarch/strcmp-avx2.S:115

115 ../sysdeps/x86_64/multiarch/strcmp-avx2.S: No such file or directory.

Edit: I'm using Linux and running

gcc -g program.c program
gdb --args ./program -f b

CodePudding user response:

There are two issues here. One, getopt() needs to know that the f option takes an argument by adding the colon, like this:

getopt(argc, argv, "i:o:f:")

Second, f is being passed to strcmp() with no checking that f has a valid value. Because getopt() wasn't expecting an argument for the f option, optarg will be NULL, so strcmp() is likely the cause of the SIGSEGV.

It would be a good idea to initialize i, o, and f to NULL then check their values after calling getopt() to see if they point to a valid argument string before using them.

CodePudding user response:

  1. If your program is called with -f it will crash as strcmp() expects two strings and the first argument is NULL which is not a string. The is due to a missing guard on the call to strcmp().
  2. If your program requires -f to have an argument then the optstring should be i:o:f: (missing the : after f). This means optarg isn't NULL when processing the f option.
  3. If your program is called without -f then the variable f remains uninitialized and the call to strcmp() is undefined behavior. It happens to crash with f == NULL for me.
  4. getopt() returns ? for invalid options, I would say it's bad form to not handle that either explicitly or with a default.
  5. Finally, I suggest using a for(;;) to avoid the assignment that is also an expression. It's sufficiently error prune that gcc insist on wrapping the assignment in parenthesis. This minimizes the scope of the variable c, and it's cleaner to handle all return values from getopt() in the same switch. If you are allergic to goto use a flag instead.
#define _POSIX_C_SOURCE 2
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv) {
    char *f = NULL;
    char *i = NULL;
    char *o = NULL;
    for(;;) {
        int c = getopt(argc, argv, "i:o:f:");
        switch (c) {
            case -1:
                goto done;
            case '?':
                // getopt generates error message
                break;
            case 'f':
                f = optarg;
                break;
            case 'i':
                i = optarg;
                break;
            case 'o':
                o = optarg;
                break;
        }
    }
done:
    printf("%sb\n", f && !strcmp(f, "b") ? "" : "not ");
    return 0;
}

and here is sample executions:

./a.out
not b
./a.out -f
./a.out: option requires an argument -- 'f'
not b
./a.out -f a
not b
./a.out -f b
b
  • Related