For some reason, I'm getting a segmentation fault when main() exits with the following code:
Code:
#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <unistd.h>
using std::cout;
using std::endl;
using std::flush;
using std::fill;
void moveTortoise(int *);
void moveHare(int *);
void race(char *);
void checkCollision(int *,int * ,char *);
bool isWinner(int *, int *);
const int TICK_MS = 10000;
const int TRACK_LENGTH = 70;
const int FINISH = TRACK_LENGTH - 1;
const char HARE_CHAR = 'H';
const char TORTOISE_CHAR = 'T';
int main() {
char track[TRACK_LENGTH + 1] = {0};
srand(time(0));
std::fill(track, track + FINISH, 45);
track[0] = HARE_CHAR;
cout << "BANG !!!!!\nAND THEY'RE OFF !!!!!" << endl;
race(track);
return 0;
}
void race(char *track) {
int hare_position = 0;
int tortoise_position = 0;
while (!isWinner(&hare_position, &tortoise_position)) {
usleep(TICK_MS);
track[tortoise_position] = '-';
track[hare_position] = '-';
moveTortoise(&tortoise_position);
moveHare(&hare_position);
track[tortoise_position] = TORTOISE_CHAR;
track[hare_position] = HARE_CHAR;
checkCollision(&hare_position, &tortoise_position, track);
cout << "\r" << track << flush;
}
}
void moveTortoise(int *position) {
int move = 0;
move = 1 + rand() % 10;
move <= 5 ? *position += 3 : (move <= 7 ? *position -= 6 : *position++);
*position = *position > 0 ? (*position > FINISH ? FINISH : *position) : 0;
}
void moveHare(int *position) {
int move = 1 + rand() % 10;
move == 1 ? *position -= 12 : (move <= 3 ? *position -= 2 : (move <= 6 ? *position++ : (move <= 8 ? *position += 9 : 0)));
*position = *position > 0 ? (*position > FINISH ? FINISH : *position) : 0;
}
void checkCollision(int *hare, int *tortoise, char *track) {
static int start = 0;
if (start > 0) {
std::fill(track + start, track + start + 7, 45);
start = 0;
}
if (*hare == *tortoise) {
start = *hare > 15 ? *hare - 8 : *hare + 2;
strncpy(track + start, "OUCH!!!", 7);
}
}
bool isWinner(int *hare, int *tortoise) {
if ((*hare == FINISH) && (*tortoise == FINISH)) {
cout << endl << "It's a tie." << endl;
return true;
}
if (*hare == FINISH) {
cout << endl << "Hare wins. Yuch." << endl;
return true;
}
if (*tortoise == FINISH) {
cout << endl << "TORTOISE WINS!!! YAY!!!" << endl;
return true;
}
return false;
}
I can't find anywhere that I would be overwriting the array bound, and everything runs perfectly until the program attempts to exit. Valgrind reports:
Code:
==5972== Invalid read of size 8
==5972== at 0x400A69: main (in /[path]/race)
==5972== Address 0x6fffffff8 is not stack'd, malloc'd or (recently) free'd
==5972==
==5972==
==5972== Process terminating with default action of signal 11 (SIGSEGV)
==5972== Access not within mapped region at address 0x6FFFFFFF8
==5972== at 0x400A69: main (in /[path]/race)
==5972== If you believe this happened as a result of a stack
==5972== overflow in your program's main thread (unlikely but
==5972== possible), you can try to increase the size of the
==5972== main thread stack using the --main-stacksize= flag.
==5972== The main thread stack size used in this run was 8388608.
==5972==
==5972== HEAP SUMMARY:
==5972== in use at exit: 0 bytes in 0 blocks
==5972== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==5972==
==5972== All heap blocks were freed -- no leaks are possible
==5972==
==5972== For counts of detected and suppressed errors, rerun with: -v
==5972== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
Segmentation fault (core dumped)
I realize that using vectors instead of pointers would be the definative solution, but I'm a noob taking a C++ class and my assignment calls for use of char arrays and pointer passing. My environment is Linux Mint 13 using g++ 4.6.3-1 with default compile options (g++ file.cpp). I suspect I might be passing a bad array to cout, in that when I display the array positions returned by moveTortoise() and moveHare(), it doesn't seg fault on exit:
Code:
//SNIP
moveTortoise(&tortoise_position);
moveHare(&hare_position);
//Adding the line below equals no segmentation fault.
cout << tortoise_position << " " << hare_position;
track[tortoise_position] = TORTOISE_CHAR;
track[hare_position] = HARE_CHAR;
//SNIP
Any ideas?