views:

92

answers:

3

Getting a weird segmentation fault on following code when I try to pass a number into my application on command line.

int offset = 3;

int main(int argc, char *argv[]) {
    // Check for arguments to see whether there is a custom offset
    if (argc == 2) {
        // If argc == 2 then we have a offset?
        if (isdigit((unsigned char)*argv[1])) {
            offset = atoi(*argv[1]);
            printf("Offset changed to: %d\n", offset);
        } else {
            printf("Offset not changed due to %s not being a number.\n", *argv[1]);
        }
    } else if(argc >= 2) {
        // If argc >= 2 then we have too many arguments
        printf("Too many arguments.");
        return 0;
    }
}
+4  A: 

argv[1] is already a string (of type char*), so writing *argv[1] dereferencing to the first byte which causes your segfault when passing that byte to atoi() and printf().

Fix it to:

offset = atoi(argv[1]);

and

printf("Offset not changed due to %s not being a number.\n", argv[1]);

cytrinox
Still segmentation fault :-/
Aran
ups, wrong line fixed :) now it should work
cytrinox
@Aran: What kind of arguments are you providing ?
Saurabh Manchanda
@cytrinox got it now... :-)
Aran
@Aran Saurabh is correct, if you pass 2foo as argument, isdigit() returns true, but atoi() would try to convert "2foo" to an integer which fails. You have to check the whole argument, not only the first byte.
cytrinox
+2  A: 

The problem is the call to atoi. It expects a string. Change it to

   offset = atoi(argv[1]);
Jochen Walter
Aran is checking only the first character whether it is a digit. An argument like 0Saurabh would still be invalid.
Saurabh Manchanda
It would convert the initial portion of the string yielding 0. It's not clear if this what the questioner wants, but it does not cause a segmentation error any more.
Jochen Walter
+5  A: 

The real problem with your code is that you are trying to call functions that you didn't declare (you must be using a C89/90 compiler). You call isdigit. You call printf. You call atoi. You call the latter two incorrectly. And the only reason the compiler cannot inform you about these functions being called incorrectly is that you forgot to declare them.

Include <ctype.h>, <stdlib.h> and <stdio.h> at the beginning of your source file, so that the compiler knows the proper parameter types for atoi and other functions. Once you do that, you should be able to figure out the problem with the atoi, because the compiler will issue a diagnostic message explaining the problem. Then you can change the call accordingly. Some compilers will be able to detect the problem with printf call as well.

Note, that even if you change the atoi and printf calls as recommended in other answers (i.e. to atoi(argv[1]) etc.), your code will still remain invalid, because in C89/90 calling printf without declaring it first leads to undefined behavior (and in C99 it is flat-out illegal to call any function without declaring it first).

AndreyT
And the compiler would tell you that you were trying to call functions that you didn't declare, if you compiled with `-Wall`. (Or the local equivalent, but the references to segmentation faults suggest Unix and hence GCC or something with compatible options.)
John Marshall
I had all the necessary includes, I just excluded them to reduce the amount of code copied...
Aran
@Aran: If you had all the necessary includes, then how did you manage to compile your `atoi(*argv[1])`? Any C compiler will raise all kinds of hell at an attempt to pass `char` value when a pointer value is expected.
AndreyT