Ethan Ladwig
Ethan Ladwig

Reputation: 21

Why does this segmentation fault?

I was trying to make a factorial program that takes input from the terminal but it doesn't work.. giving it anything but no arguments gives a segmentation fault

// factorial calculator
#include <iostream>
using namespace std;

long factorial(long a) {
    if (a > 1)
        return (a * factorial(a-1));
    else
        return 1;
}

int main(int argc, char *argv[]) {
    long number = (long) argv[1];
    cout << number << "! = " << factorial(number) << '\n';
    return 0;
}

also for some reason number has the value of 140732199978159 when I do ./factorial 2

(all I got from attempting to find an answer by searching was that a segfault means that I'm accessing something I'm not supposed to. I don't understand where I've done that here.)

Upvotes: 1

Views: 77

Answers (2)

Silvio Mayolo
Silvio Mayolo

Reputation: 70267

long number = (long) argv[1];

This takes argv[1] and casts it to long. argv is a char*[] (for simplicity, I'll assume it's the very similar type char** for this explanation). Hence, argv[1] is a char*. Casting a char* to long takes its address as a numerical value. That's a position in memory on your computer and not helpful for calculating the factorial.

Consider strtol, a built-in C++ function that does exactly what you want.

long number = std::strtol(argv[1], nullptr, 10);

10 is the numerical base (we do our math in base 10, generally). The second argument is optional and not necessary for our use case, so we pass nullptr since we don't need it.

Upvotes: 4

Sam Varshavchik
Sam Varshavchik

Reputation: 118300

(long) argv[1];

argv[1] is a const char *, a pointer to some unspecified number of characters.

Even if that character string happens to be "2", converting the pointer to a long value, like this, does not get you an actual number 2. That's not how C++ works. All this does is reinterpret the raw memory address, that the pointer is pointing to. You get, pretty much, a junk number, and attempting to compute its factorial results in equally meaningless results.

You'll need to use some suitable library function, like atol from the C library, or std::stol from the C++ library (with some overhead due to a temporary conversion to a std::string) in order to get the expected results.

Upvotes: 1

Related Questions