Segmentation fault while running command line arguments

Doing a "guessing game" where the user can edit the difficulty and guessing range at the command line:

Essentially, the user can run the program and then type -d "difficulty" -n "range" such as;

-d easy -n 150, to give him a certain number of guesses to get the number between 1 and 150

likewise, he can enter

-n 300 -d normal (guessing between 1 and 300 on normal difficulty)
-n 84 (guessing between 1 and 84 with unlimited tries)
-d hard (guessing between 1 and 100 on hard difficulty)

any order that he/she wants. If the user runs the program without any command line arguments, it will simply default to unlimited guesses between 1 and 100.

Beware, this code is rather ugly but it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <iostream>
#include <string.h>
#include <cstdlib>
#include <cmath>
using namespace std;

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

if (strcmp (argv[1], "-n") == 0 && strcmp (argv[3], "-d") == 0) //if user inputs order -n X -d difficulty
{
	int i;
	float j;
	i = atoi (argv[2]); 	//convert string into integer
	srand (time(NULL));
	int x, y = rand() % i;
	if (strcmp (argv[4], "easy") == 0)
		j = 0.8;
	if (strcmp (argv[4], "medium") == 0)
		j = 0.6;
	if (strcmp (argv[4], "hard") == 0)
		j = 0.4;
	if (strcmp (argv[4], "unlimited") == 0)
		j = 1000;
	
	cout << "I'm thinking of a number between 0 and " << i << ". Can you guess it?" << endl;
	{
		for (int a = j*log2(i); a > 0 ; a--)
		{
			cin >> x;
			if (x > y)
				cout << "I'm thinking of a smaller number. Please try again." << endl;
			else
			if (x < y)
				cout << "I'm thinking of a larger number. Please try again." << endl;
			if (x == y)
				goto correct;
			else;
		}
		cout << "Out of tries! You lost." <<endl;
		return 0;
	}
	correct:
	cout << "Correct! You guessed the secret number!" << endl;
	return 0;
}
if (strcmp (argv[1], "-d") == 0 && strcmp(argv[3], "-n") == 0) //if the user inputs order -d diff -n x
{
	int i;
	float j;
	i = atoi (argv[4]); 	//convert string into integer
	srand (time(NULL));
	int x, y = rand() % i;
	if (strcmp (argv[2], "easy") == 0)
		j = 0.8;
	if (strcmp (argv[2], "medium") == 0)
		j = 0.6;
	if (strcmp (argv[2], "hard") == 0)
		j = 0.4;
	if (strcmp (argv[2], "unlimited") == 0)
		j = 1000;
	
	cout << "I'm thinking of a number between 0 and " << i << ". Can you guess it?" << endl;
	{
		for (int a = j*log2(i); a > 0 ; a--)
		{
			cin >> x;
			if (x > y)
				cout << "I'm thinking of a smaller number. Please try again." << endl;
			else
			if (x < y)
				cout << "I'm thinking of a larger number. Please try again." << endl;
			if (x == y)
				goto correct1;
			else;
		}
		cout << "Out of tries! You lost." <<endl;
		return 0;
	}
	correct1:
	cout << "Correct! You guessed the secret number!" << endl;
	return 0;
}
if (strcmp (argv[1], "-n") == 0 && strcmp (argv[3], "-d") != 0) //if the user inputs -n X
{
	int i;
	i = atoi (argv[2]); 	//convert string into integer
	srand (time(NULL));
	int x, y = rand() % i;
	
	cout << "I'm thinking of a number between 0 and " << i << ". Can you guess it?" << endl;

	do
	{
		cin >> x;
		if (x > y)
			cout << "I'm thinking of a smaller number. Please try again." << endl;
		else
		if (x < y)
			cout << "I'm thinking of a larger number. Please try again." << endl;
	}
	while (x != y);

	cout << "Correct! You guessed the secret number!" << endl;
	return 0;
}
if (strcmp (argv[1], "-d") == 0 && strcmp(argv[3], "-n") != 0) //if the user inputs -d difficulty
{
	float j;
	srand (time(NULL));
	int x, y = rand() % 101;
	if (strcmp (argv[2], "easy") == 0)
		j = 0.8;
	if (strcmp (argv[2], "medium") == 0)
		j = 0.6;
	if (strcmp (argv[2], "hard") == 0)
		j = 0.4;
	if (strcmp (argv[2], "unlimited") == 0)
		j = 1000;
	
	cout << "I'm thinking of a number between 0 and 100. Can you guess it?" << endl;
	{
		for (int a = j*log2(100); a > 0 ; a--)
		{
			cin >> x;
			if (x > y)
				cout << "I'm thinking of a smaller number. Please try again." << endl;
			else
			if (x < y)
				cout << "I'm thinking of a larger number. Please try again." << endl;
			if (x == y)
				goto correct2;
			else;
		}
		cout << "Out of tries! You lost." <<endl;
		return 0;
	}
	correct2:
	cout << "Correct! You guessed the secret number!" << endl;
	return 0;
}

if (argc == 1) //blank input

	int i;
	srand (time(NULL));
	int x, y = rand() % 101;
	
	cout << "I'm thinking of a number between 0 and 100. Can you guess it?" << endl;

	do
	{
		cin >> x;
		if (x > y)
			cout << "I'm thinking of a smaller number. Please try again." << endl;
		else
		if (x < y)
			cout << "I'm thinking of a larger number. Please try again." << endl;
	}
	while (x != y);

	cout << "Correct! You guessed the secret number!" << endl;
	return 0;
}


Currently, inputting -d "difficulty" -n "range" or -n "range -d "difficulty" works fine. However, if I just do -d "difficulty" or -n "range" or without any arguments, I get a Segmentation fault error.

I know this code is ugly as sin and I also haven't done any argc/argv checks yet - right now I'm just trying to figure this particular segmentation fault error that keeps popping up.
Last edited on


Here's the output from running the code under gdb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2 () at ../sysdeps/x86_64/multiarch/../strcmp.S:99
99	../sysdeps/x86_64/multiarch/../strcmp.S: No such file or directory.
	in ../sysdeps/x86_64/multiarch/../strcmp.S
(gdb) up
#1  0x0000000000400bac in main (argc=1, argv=0x7fffffffe3e8) at bad12.cpp:10
10	if (strcmp (argv[1], "-n") == 0 && strcmp (argv[3], "-d") == 0) //if user inputs order -n X -d difficulty
(gdb) print argv[1]
$1 = 0x0
(gdb) print argv[3]
$2 = 0x7fffffffe6bd "SSH_AGENT_PID=1228"
(gdb) print argv[2]
$3 = 0x7fffffffe6a0 "ORBIT_SOCKETDIR=/tmp/orbit-j"
(gdb) print argv[0]
$4 = 0x7fffffffe68a "/home/j/badCode/a.out"
(gdb) 



You can see that argv[1] points to address value 0x0; that is, it is a null pointer. It seems that if strcmp is fed a null pointer, it tries to dereference it and you get a segfault. This is not true of all implementations, but clearly it is of yours and mine. As I recall, feeding null pointers to these cstring functions produces undefined behaviour.

You can also see the leftover bits in memory from previous things I've been doing :)
Last edited on
The problem is the order in which the checks are made. Since your very first if statement uses argv[1], it MUST have a value. Try checking for no arguments first.
Last edited on
Thanks, but I'm still getting a segmentation fault even after checking for no arguments - how do I make it such that argv[1] isn't a null pointer?
The only way to make argv[1] not a null pointer is to feed in more than one argument.

Checking for no arguments won't do it; by convention, argc will always be at least one, because the contents of argv[0] are the command line used to run the programme. Don't check for no arguments; check for less than two arguments, and if there are less than two, do not try to dereference argv[1].
I am feeding it two arguments, however - such as ./program -d -easy or ./program -n 150, and I'm also supposed to run it without any arguments (default setting) - the only time when I'm not getting any segmentation errors is when I feed it 4 arguments such as ./program -d easy -n 300
When you feed it two arguments, you have non-null pointers for argv[0], argv[1] and argv[2].

Does your code still go on to then try to do something with argv[3] and argv[4]?
Last edited on
I copied your code exactly and then moved your very last if statement (if(argc ==1)) to be the first check and it worked (after I corrected some syntax errors).

./test
I'm thinking of a number between 0 and 100. Can you guess it?
5
I'm thinking of a larger number. Please try again.
10
I'm thinking of a larger number. Please try again.
100
I'm thinking of a smaller number. Please try again.
50
I'm thinking of a smaller number. Please try again.
40
I'm thinking of a smaller number. Please try again.
30
I'm thinking of a smaller number. Please try again.
20
I'm thinking of a smaller number. Please try again.
15
I'm thinking of a smaller number. Please try again.
11
Correct! You guessed the secret number!


Also, when compiling, I got some warnings:

g++ -Wall test.cpp -o test
test.cpp: In function âint main(int, char**)â:
test.cpp:11: warning: unused variable âiâ
test.cpp:50: warning: converting to âintâ from âdoubleâ
test.cpp:87: warning: converting to âintâ from âdoubleâ
test.cpp:145: warning: converting to âintâ from âdoubleâ


I'm not sure where you are getting the seg fault? You are missing some important '{' in a couple of places, though. That's what I had to correct to get it to compile.

Granted, I did not test the other conditions. I will and see if that causes a problem.
Last edited on
Here's what happened so far:

[nagios@tools ~]$ ./test -n 150
Segmentation fault
[nagios@tools ~]$ ./test -d easy -n 150
I'm thinking of a number between 0 and 150. Can you guess it?
75
I'm thinking of a larger number. Please try again.
100
I'm thinking of a smaller number. Please try again.
80
I'm thinking of a larger number. Please try again.
90
I'm thinking of a smaller number. Please try again.
85
Correct! You guessed the secret number!
[nagios@tools ~]$
I think the overall problem is that you need to first test for the number of arguments and based on that test, proceed with the code selection structure. The way the code is written, you are still trying to use values that don't exist (depending on the user's input). More often than not, a seg fault means that you tried to read or write past the bounds of an array. That's the clue I will give you for now. See if you can figure out how to fix it. Ask specific questions if you get stuck.
Last edited on
Topic archived. No new replies allowed.