0

When I use this compiler command:

gcc ../main.c -w -o sc

And this code:

/* sc - a simple calculator */

/* glibc */
#include <stdio.h>
#include <stdlib.h>

/* global variables */ 
int ans;

void help()
{
    printf("Type in an equation (2 + 2) and it will solve it. (4)\n");
    printf("-- remember spaces between characters.\n");
}

void error()
{
    printf("That value is not accepted.\n");
    printf("---------------------------\n");
    help();
}

int main(int argc, char *argv[])
{
    if(strcmp(argv[1], "help") == 0) {
        help();
    } else if(argc == 4) {
        if( /* Removed calculator function */ (argc, argv) != 0) {
            error();
            return 2;
        }
    } else {
        error();
        return 1;
    }

    return 0;
}

When I run the binary without any arguments this is the output:

Segmentation fault (core dumped)

Why does it fail when it falls to the else and not when it has arguments?

  • 3
    If you aren't passing arguments, then you're doing `strcmp(argv[1], "help")` when `argv[1]` is NULL, which is bad. You need to check `argc` for arguments and avoid accessing `argv` values that do not exist. – lurker Feb 15 '15 at 02:40
  • this `(argc, argv) != 0` does not compare both values. – Iharob Al Asimi Feb 15 '15 at 02:43

1 Answers1

3

If you aren't passing arguments, then you're doing strcmp(argv[1], "help") when argv[1] is NULL, which is bad. You need to check argc for arguments and avoid accessing argv values that do not exist. For example:

if ((argc >= 2) && (strcmp(argv[1], "help") == 0)) {
    help();
} else if(argc == 4) {

If argc is not at least 2, then argv[1] is going to be NULL and strcmp will segfault. (NOTE: argv[0] is the command name itself, the executable name, so arvc should always be at least 1 if you are executing your command from the command line.)

lurker
  • 56,987
  • 9
  • 69
  • 103
  • To OP: `argv[0]` is always the name of the program; `main`, in your case. – Fiddling Bits Feb 15 '15 at 02:44
  • It's also possible to have `argc == 0`, in which case `argv[1]` is undefined – M.M Feb 15 '15 at 03:23
  • @MattMcNabb if `argc == 1`, then there are no command line arguments and `argv[1]` is undefined. The "first" argument is the command itself, and is `argv[0]`, which corresponds to `argc == 1`. Although there are cases where one program can exec another and have `argv[0]` NULL and `argc == 0`. – lurker Feb 15 '15 at 03:28
  • @lurker `argv[argc]` is always NULL, so if `argc == 1` then `argv[1]` is NULL and `argv[0]` should contain the commandline. – M.M Feb 15 '15 at 03:45
  • @MattMcNabb, yes I'm aware of that. I believe my comment is consistent with that. – lurker Feb 15 '15 at 03:48
  • @lurker you said `argv[1]` is undefined when `argc == 1`, which is wrong – M.M Feb 15 '15 at 04:10
  • @MattMcNabb I see. Yes, I meant NULL (as I indicated in my answer), not strictly "undefined". As you say, if `argv[argc]` is always NULL, so it goes that if `argc == 1` then `argv[1] == NULL`. – lurker Feb 15 '15 at 04:17
  • to be clear, NULL is well-defined, it is completely different to "undefined" which means [anything can happen](http://stackoverflow.com/a/4105123/1505939) – M.M Feb 15 '15 at 04:59
  • @MattMcNabb yes, thank you for clarifying. I am aware and was sloppy in my comment. I understand the difference. – lurker Feb 15 '15 at 10:36