Dealing with pointers causing a segmentation fault in C++ [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Here is the function in question:
#include <cstdlib>
#include <string>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "Train.h"
#include "Platform.h"
const int NUM_TRAINS = 4;
const int NUM_NORTHERNLY_TRAINS = NUM_TRAINS / 2;
const int NUM_SOUTHERNLY_TRAINS = NUM_TRAINS - NUM_NORTHERNLY_TRAINS;
const int NUM_LOOPS = 16;
const char* TRAIN_NAME_ARRAY[NUM_TRAINS]
= { "Thomas the Tank-Engine",
"Percy the Small Engine",
"California Zephyr",
"Tokaido Shinkansen"
};
const int TRAIN_TRANSIT_TIME_MSECS[NUM_TRAINS]
= { 10000, // Thomas
10000, // Percy
5000, // CA Zephyr
1000 // Bullet train
};
Platform northBoundPlatform("North-bound Platform");
Platform southBoundPlatform("South-bound Platform");
void* initiallyNorthernly (void* vPtr)
{
Train* id = ((Train*)vPtr);
for (int i = 0; i < NUM_LOOPS; i++)
{
northBoundPlatform.arrive(id);
northBoundPlatform.leave();
pause();
southBoundPlatform.arrive(id);
southBoundPlatform.leave();
pause();
}
return((void*)id);
}
void* initiallySouthernly (void* vPtr)
{
Train* id = (Train*)vPtr;
for (int i = 0; i < NUM_LOOPS; i++)
{
southBoundPlatform.arrive(id);
southBoundPlatform.leave();
pause();
northBoundPlatform.arrive(id);
northBoundPlatform.leave();
pause();
}
return((void*)id);
}
int main ()
{
pthread_t tidArray[NUM_TRAINS];
Train* trainArray[NUM_TRAINS];
pthread_t tidArray2[NUM_NORTHERNLY_TRAINS];
Train* trainArray2[NUM_NORTHERNLY_TRAINS];
pthread_t tidArray3[NUM_SOUTHERNLY_TRAINS];
Train* trainArray3[NUM_SOUTHERNLY_TRAINS];
for (int i = 0; i < NUM_TRAINS; i++)
{ trainArray[i] = new Train(TRAIN_NAME_ARRAY[i],TRAIN_TRANSIT_TIME_MSECS[i]);
}
int trainInd = 0;
for (int i = 0; i < NUM_NORTHERNLY_TRAINS; i++)
{
pthread_create(&tidArray2[i], NULL, initiallyNorthernly,&trainArray2[i]);
}
for (int i = 0; i < NUM_SOUTHERNLY_TRAINS; i++)
{
pthread_create(&tidArray3[i], NULL, initiallySouthernly,&trainArray3[i]);
}
for (int i = 0; i < NUM_TRAINS; i++)
{
trainArray[i] = NULL;
// Wait for all Train threads. Also, get the pointers to the Train objects
// and delete() them because they were created by 'new'
pthread_join(tidArray[i], (void**)&trainInd);
pthread_join(tidArray2[i],(void**)&trainInd);
pthread_join(tidArray3[i],(void**)&trainInd);
}
return(EXIT_SUCCESS);
}
Here are the appropriate header files:
Train.h
class Train
{
std::string name_;
int pauseTimeUsecs_;
public :
Train (const std::string& newName,
int newPauseTimeUsecs
)
{
name_ = newName;
pauseTimeUsecs_ = newPauseTimeUsecs;
std::cout << getName() << " leaving the trainyard.\n";
}
~Train ()
{
std::cout << getName() << " going back to the trainyard\n";
}
const std::string&
getName ()
const
{ return(name_); }
void pause ()
const
{
usleep(pauseTimeUsecs_);
}
};
Platform.h
class Platform
{
std::string name_;
Train* trainPtr_;
pthread_mutex_t mutexLock_;
pthread_cond_t notEmptyCond_;
pthread_cond_t notFullCond_;
public :
Platform (const std::string& newName
)
{
name_ = newName;
trainPtr_ = NULL;
pthread_mutex_init(&mutexLock_,NULL);
pthread_cond_init(&notEmptyCond_,NULL);
pthread_cond_init(&notFullCond_,NULL);
}
// PURPOSE: To release resources. No parameters. No return value.
~Platform ()
{
pthread_mutex_destroy(&mutexLock_);
pthread_cond_destroy(&notEmptyCond_);
pthread_cond_destroy(&notFullCond_);
}
const std::string&
getName ()
const
{
return(name_);
}
Train* getTrainPtr
()
const
{
return(trainPtr_);
}
void arrive (Train* newTrainPtr
)
{
pthread_mutex_lock(&mutexLock_);
while (getTrainPtr() != NULL)
{
std::cout << getTrainPtr()->getName()
<< " is at " << getName()
<< ", " << newTrainPtr->getName()
<< " must wait.\n";
usleep(10) + rand() % 10;
pthread_cond_wait(&notFullCond_,&mutexLock_);
}
std::cout << newTrainPtr->getName() << " arriving at " << getName() << "\n";
trainPtr_ = newTrainPtr;
usleep(10 + rand() % 10);
pthread_mutex_unlock(&mutexLock_);
pthread_cond_signal(&notEmptyCond_);
}
Train* leave ()
{
pthread_mutex_lock(&mutexLock_);
while (getTrainPtr() == NULL)
{
std::cout << "No train at " << getName() << "!\n";
usleep(10 + rand() % 10);
pthread_cond_wait(&notEmptyCond_,&mutexLock_);
}
Train* toReturn = getTrainPtr();
std::cout << toReturn->getName() << " leaving " << getName() << "\n";
usleep(10 + rand() % 10);
trainPtr_ = NULL;
pthread_cond_signal(&notFullCond_);
pthread_mutex_unlock(&mutexLock_);
return(toReturn);
}
};
After running with gdb, the segmentation fault is occurring when I call arrive on northBoundPlatform(a Platform object). The goal of the function is to make the train object that is pointed to by vPtr arrive() at northernPlatform, leave() at northernPlatform, pause() on the train object, arrive() at the southBoundPlatform, leave() the southBoundPlatform, pause() on the object again, and finally return a pointer to the train that was used.
I am not sure if I am casting vPtr into a Train* correctly which is causing a segmentation fault. I can provide the rest of the main code if necessary. Any help is appreciated.

Your main() function has two for loops for each of NUM_NORTHERNLY_TRAINS, using initiallyNorthernly and initiallySouthernly, but the second loop should be looping with NUM_SOUTHERNLY_TRAINS instead.

Related

.exe file has triggered a breakpoint

I am writing a list-based multi-stack program. At first everything worked fine. Then I added a few exceptions. After that, the program began to build normally, but after throwing an exception, the program breaks. I opened the debugger and reached the place of error. There I found a place where another exception is thrown. But all that was written there is "MultiListStack.exe has triggered a breakpoint.". Please tell me, because of what it can be and how to fix it? Below I attach the code:
tmultiroot.h
//tmultiroot.h
//base abstract class for inheritance
#ifndef __MULTROOT_H__
#define __MULTROOT_H__
const int MemLimit = 4; // memory size
const int StackNum = 2; // number of stacks
typedef int TElem; // type of element
class TMultiRoot:
{
protected:
TElem Mem[MemLimit]; // memory for stacks (int array of MemLimit elements)
int DefaultStack; // current stack number
public:
TMultiRoot() { DefaultStack = 0; }
virtual bool IsEmpty(int ns) const = 0; // void control
virtual bool IsFull (int ns) const = 0; // overflow control
virtual void Put (int ns, const TData &Val) = 0; // put on the stack
virtual TData Get (int ns) = 0; // take from stack with deletion
// methods for working with the current stack
void SetDefaultStack(int ns) { DefaultStack = ns; } //current stack
int IsEmpty(void) const { return IsEmpty(DefaultStack); } // empty?
int IsFull(void) const { return IsFull (DefaultStack); } // full of?
void Put(const TData &Val) { Put(DefaultStack, Val); } // in the stack
TData Get(void) { return Get(DefaultStack); } // from the stack
};
#endif
multiliststack.h
//multiliststack.h
#ifndef __MULTILISTSTACK_H__
#define __MULTILISTSTACK_H__
#include "tmultiroot.h"
typedef int TElem; // type of element
class TMultiListStack: public TMultiRoot
{
protected:
int NextLink[MemLimit]; // next link index
int StackInd[StackNum]; // stack top index
int FirstFreeLink; // first free link index
public:
TMultiListStack();
virtual bool IsEmpty(int ns) const; // void control
virtual bool IsFull (int ns) const; // overflow control
virtual void Put (int ns, const TData &Val); // put on the stack
virtual TData Get (int ns); // take from stack with deletion
// utility methods
void Print(); // print stack values
int IsValid() { return 0; } // structure testing
};
#endif
exceptions.h
//exceptions.h
#ifndef _exceptions_h
#define _exceptions_h
//Exception class
class Exception{
protected:
int Line;
char* File;
char* Func;
char* Desc;
public:
Exception() {};//default constructor
Exception(int _Line, char* _File, char* _Func, char* _Desc); //constructor
Exception(const Exception& e); //copy constructor
~Exception(); //destructor
virtual void debug_print(); //display error message
virtual char* GetDesc(); //return error message
};
//stack exception class
class StackExc: public Exception {
protected:
int exc;//exception code, 0 - nomem, 1 - empty, 2 - full
public:
StackExc() {};//default constructor
StackExc(int _Line, char* _File, char* _Func, char* _Desc, int exc); //constructor
StackExc::~StackExc(); //destructor
int GetExc(); //get exception code
virtual void debug_print(); //display error message
};
#endif
ecxeptions.cpp
//exceptions.cpp
#include <cstring>
#include <iostream>
#include "exceptions.h"
//Exception class
Exception::Exception(int _Line, char* _File, char* _Func, char* _Desc) {
Line = _Line;
int size = strlen(_File) + 1;
File = new char[size];
strcpy(File, _File);
Func = new char[size];
strcpy(Func, _Func);
Desc = new char[size];
strcpy(Desc, _Desc);
}
//copy constructor
Exception::Exception(const Exception& e) {
Line = e.Line;
int size = strlen(e.File) + 1;
File = new char[size];
strcpy(File, e.File);
Func = new char[size];
strcpy(Func, e.Func);
Desc = new char[size];
strcpy(Desc, e.Desc);
}
//destructor
Exception::~Exception() {
delete[] File;
delete[] Func;
delete[] Desc;
}
//display exception
void Exception::debug_print() {
std::cerr << Line << " " << File << " " << Func << " " << Desc << std::endl;
}
char * Exception::GetDesc()
{
return Desc;
}
//stack exception class
StackExc::StackExc(int _Line, char* _File, char* _Func, char* _Desc, int exc)
: Exception(_Line, _File, _Func, _Desc), exc(exc) {
}
//destructor
StackExc::~StackExc() {
delete[] File;
delete[] Func;
delete[] Desc;
}
int StackExc::GetExc() {
return exc;
}
//display exception
void StackExc::debug_print() {
std::cerr << Desc << std::endl;
}
multiliststack.cpp
//multiliststack.cpp
#include <stdio.h>
#include "tmultiliststack.h"
#include "exceptions.cpp"
TMultiListStack::TMultiListStack()
{
for (int i = 0; i < MemLimit; i++)
NextLink[i] = i + 1;
NextLink[MemLimit - 1] = -1;
FirstFreeLink = 0;
for (int i = 0; i < StackNum; i++)
StackInd[i] = -1;
}
bool TMultiListStack::IsEmpty(int ns) const // void control
{
return StackInd[ns] < 0;
}
bool TMultiListStack::IsFull(int ns) const // overflow control
{
return FirstFreeLink < 0;
}
void TMultiListStack::Put(int ns, const TData &Val) // put on the stack
{
if (IsFull(ns)) {
throw StackExc(__LINE__, __FILE__, __FUNCTION__, "DataFull", 2); //after throwing this exception
} //it is being processed in main
else // And then an exception "MultiListStack.exe has triggered a breakpoint." occurs on this line
{
int k = FirstFreeLink;
FirstFreeLink = NextLink[k];
Mem[k] = Val;
NextLink[k] = StackInd[ns];
StackInd[ns] = k;
}
}
TData TMultiListStack::Get(int ns) // take from stack with deletion
{
TData temp = -1;
if (IsEmpty(ns))
throw StackExc(__LINE__, __FILE__, __FUNCTION__, "DataEmpty", 1);
else
{
int k = StackInd[ns];
temp = Mem[k];
StackInd[ns] = NextLink[k];
NextLink[k] = FirstFreeLink;
FirstFreeLink = k;
}
return temp;
}
void TMultiListStack::Print() // print stack values
{
int pind, ind, k;
for (int ns = 0; ns < StackNum; ns++)
{
printf("ns=%d -> ", ns);
pind = -1;
ind = StackInd[ns];
while (ind > -1) // pointer wrapping
{
k = NextLink[ind];
NextLink[ind] = pind;
pind = ind;
ind = k;
}
ind = pind;
pind = -1;
while (ind > -1) // pointer recovery and printing
{
printf("%d ", Mem[ind]);
k = NextLink[ind];
NextLink[ind] = pind;
pind = ind;
ind = k;
}
printf("\n");
}
}
main.cpp
#include <windows.h>
#include <conio.h>
#include <iostream>
#include "tmultiliststack.h"
using namespace std;
void main()
{
TMultiListStack mst;
int ms = 2, ns, code, temp, val = 0;
setlocale(LC_ALL, "Russian");
srand(1);
cout << "System Testing N Stacks" << endl;
while (1)
{
try {
val++;
code = random(4); // operation
ns = random(ms); // stack number
Sleep(1000);
if (code < 3) {
cout << "Put " << val << " in " << ns << endl;
mst.Put(ns, val);
mst.Print();
}
else {
cout << "Get from " << ns << endl;
temp = mst.Get(ns);
mst.Print();
}
}
catch (StackExc exc) {
exc.debug_print();
}
if (_kbhit())
break;
}
cout << "Stack Printing" << endl;
mst.Print();
}
When the program starts, 4 values ​​are put on the zero stack. But at the fifth iteration, when the fifth value is to be added to the zero stack, overflow occurs. Because of this, my exception is thrown. Then it is processed in main. And after that, this incomprehensible exception is thrown. No details about it are displayed, so I don’t understand what to do. Tell me, please, how to fix it?

C++ own Stack of objects. What is copied at push()?

Well, i implemented a FIFO stack (push,pop) stack in a Class with mem allocated ints.
So i asked to myself: if "int" is a datatype, why i cannot push "ADTs" to my own stack.
Then i came with this code:
#include <iostream>
class Person {
std::string name;
int age;
public:
Person(std::string pName = "", int pAge = 1)
{
name = pName;
age = pAge;
}
void Print()
{
std::cout << name << " " << age << std::endl;
}
};
class Stack {
Person * stack;
int size, top;
int index;
public:
Stack(int stackSize)
{
top = stackSize -1;
index = top;
stack = new Person[stackSize];
}
void push(Person person)
{
if (index < 0)
std::cout << "Stack UNDERFLOW" << "Index is: " << index << std::endl;
stack[index--] = person;
}
Person & pop()
{
if (index > top)
{
std::cout << "Stack OVERFLOW" << std::endl;
}
return stack[++index];
}
};
I know, there are stacks, queues, vectos, etc in the STL lib. I just wanted to do it by myself.
I want the stack push a copy of the object.
I'm not sure i don't know if the compiler is pushing addresses, copying the whole object (what is what i want) or what.
Please enlight me.
Here is my main() code:
int main()
{
Stack stack(100);
Person person("Lucas", 39);
for (int i = 0; i < 100; i++)
{
stack.push(person);
((Person)stack.pop()).Print();
}
return EXIT_SUCCESS;
}
To answer your question about copies, this:
stack[index--] = person;
makes a copy, because the type on both sides of the assignment is of type T.
This:
stack.push(person);
also makes a copy, because you are passing person by value. To avoid this (redundant) copy, declare push as:
void push(const T &person)
Well, what i did to solve my question was what #PaulMcKenzie said in his comment.
I created a template for the "Stack" class and any template "T" is the datatype that is passed to the this class.
About the main methond (in my question) it had an unnecesary cast to (Person) since it's implied.
Edit 2:
#Paul Sanders were right too, i was doing a redundant copy at push()
This way i solved my problem:
#include <iostream>
class Person {
std::string name;
int age;
public:
Person(std::string pName = "", int pAge = 1)
{
name = pName;
age = pAge;
}
void Print()
{
std::cout << name << " " << age << std::endl;
}
};
template <class T>
class Stack {
T * stack;
int size, top;
int index;
public:
Stack(int stackSize)
{
top = stackSize -1;
index = top;
stack = new T[stackSize];
}
void push(const T &person)
{
if (index < 0)
std::cout << "Stack UNDERFLOW" << std::endl;
stack[index--] = person;
}
T pop()
{
if (index > top)
{
std::cout << "Stack OVERFLOW" << std::endl;
}
return stack[++index];
}
};
int main()
{
Stack<Person> stack(100);
Person person1("Lucas", 39);
Person person2("Gustavo", 38);
for (int i = 0; i < 100; i++)
{
if (i % 2 == 0)
stack.push(person1);
else
stack.push(person2);
}
for (int i = 0; i < 100; i++)
stack.pop().Print();
return EXIT_SUCCESS;
}
In the example of the main() function, it creates an stack of Person objects of 100. Then i create 2 people: "Lucas" and "Gustavo" and push it intercalated to the my stack for 100 times (the first for statment).
Then the second and final for statement pop() all values and print them.

memory limit exceeded in C++ test sample

I am working on a sample test in the site: https://www.testdome.com/for-developers/solve-question/9808
I added two destructors for base class and derived class respectively to release the memory allocated by constructors. The first two requirements of this question are solve successfully, but the result give a fail as: Using timed multiple choice test as multiple choice test: Memory limit exceeded
My modified code as given below, I will appreciate if you can help to fix the fail...
#include <iostream>
#include <string>
class MultipleChoiceTest
{
public:
MultipleChoiceTest(int questionsCount)
{
this->questionsCount = questionsCount;
answers = new int[questionsCount];
for (int i = 0; i < questionsCount; i++)
{
answers[i] = -1;
}
}
void setAnswer(int questionIndex, int answer)
{
answers[questionIndex] = answer;
}
int getAnswer(int questionIndex) const
{
return answers[questionIndex];
}
~MultipleChoiceTest()
{
delete answers; // release memory
}
protected:
int questionsCount;
private:
int* answers;
};
class TimedMultipleChoiceTest : public MultipleChoiceTest
{
public:
TimedMultipleChoiceTest(int questionsCount)
: MultipleChoiceTest(questionsCount)
{
times = new int[questionsCount];
for (int i = 0; i < questionsCount; i++)
{
times[i] = 0;
}
}
void setTime(int questionIndex, int time)
{
times[questionIndex] = time;
}
int getTime(int questionIndex) const
{
return times[questionIndex];
}
~TimedMultipleChoiceTest()
{
delete times; // release memory
}
private:
int* times;
};
#ifndef RunTests
void executeTest()
{
MultipleChoiceTest test(5);
for (int i = 0; i < 5; i++)
{
test.setAnswer(i, i);
}
for (int i = 0; i < 5; i++)
{
std::cout << "Question " << i + 1 << ", correct answer: " << test.getAnswer(i) << "\n";
}
}
int main()
{
for (int i = 0; i < 3; i++)
{
std::cout << "Test: " << i + 1 << "\n";
executeTest();
}
}
#endif
you should use delete [] instead of delete to deallocate dynamic arrays.
Also, you don't seem to use the derived class but, nevertheless, the destructor in MultipleChoiceTest should be virtual

Access violation reading c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
/Unhandled exception at 0x00AB6591 in Building.exe: 0xC0000005: Access violation reading location 0x00000000./
#pragma warning (disable : 4996)
#include<iostream>
#include<string>
#include<cassert>
using namespace std;
class Building
{
private:
int height;
int area;
char*address;
public:
Building();
Building(int, int, char*);
~Building();
Building(const Building &);
Building & operator=(const Building&);
int getHeight()const;
int getArea()const;
char* getAddress()const;
void print()const;
void setHeight(int);
void setArea(int);
void setAddress(char*);
};
Building::Building()
{
height = 0;
area = 0;
address = new char[1];
address = NULL;
}
Building::Building(int h, int ar, char* a)
{
height = h;
area = ar;
address = new char[strlen(a)+1];
assert(address != NULL);
address = NULL;
}
Building::~Building()
{
delete[]address;
}
Building::Building(const Building & b)
{
height = b.height;
area = b.area;
address = new char[strlen(b.address) + 1];
assert(address != NULL);
strcpy(address,b.address);
}
Building & Building::operator=(const Building& b)
{
if (this != &b)
{
delete[]address;
height = b.height;
area = b.area;
address = new char[strlen(b.address) + 1];
assert(address != NULL);
strcpy(address, b.address);
}
return *this;
}
int Building::getHeight()const
{
return height;
}
int Building::getArea()const
{
return area;
}
char* Building::getAddress()const
{
return address;
}
void Building::print()const
{
cout << "Height = " << getHeight() << endl << "Area = " << getArea() << endl << "Address = " << getAddress() << endl;
}
void Building::setHeight(int h)
{
height = h;
}
void Building::setArea(int ar)
{
area = ar;
}
void Building::setAddress(char* adr)
{
strcpy(address, adr);
}
//==========================================================================================================
class House :public Building
{
private:
int floors;
char*name;
public:
House();
House(int,int,char*,int=0, char* =" ");
~House();
House(const House&);
House& operator=(const House&);
int getFloors()const;
char* getName()const;
void setFloors(int);
void setName(char*);
void print()const;
};
House::House()
{
floors = 0;
name = new char[1];
assert(name != NULL);
name = NULL;
}
House::House(int h, int ar, char* adr, int f, char* n) :Building(h, ar, adr)
{
floors = f;
name = new char[strlen(n) + 1];
assert(name != NULL);
strcpy(name, n);
}
House::~House()
{
delete[]name;
}
House::House(const House& h) :Building(h)
{
floors = h.floors;
name = new char[strlen(h.name) + 1];
assert(name != NULL);
strcpy(name, h.name);
}
House& House::operator=(const House&h)
{
if (this != NULL)
{
Building::operator=(h);
delete[]name;
floors = h.floors;
name = new char[strlen(h.name) + 1];
assert(name != NULL);
strcpy(name, h.name);
}
return*this;
}
int House::getFloors()const
{
return floors;
}
char* House::getName()const
{
return name;
}
void House::setFloors(int f)
{
floors = f;
}
void House::setName(char* na)
{
strcpy(name, na);
}
void House::print()const
{
Building::print();
cout << "Floors: " << getFloors() << endl << "Name: " << getName() << endl;
}
//=============================================================================================================
House getBigger(House m[], int size)// a house with bigger avarage height of a floor
{
House temp;
int max = 0;
int index = 0;
for (int i = 0; i < size; i++)
{
int avH = (m[i].getHeight() / m[i].getFloors());
if (avH >= max)
{
max = avH;
index = i;
}
}
return m[index];
}
//=============================================================================================================
int main()
{
House h1(16,400,"Bla street",4,"Marion");
h1.print();
House h2;
h2.setHouse();
h2.print();
House h3;
h3.setHouse();
h3.print();
House arr[] = { h1, h2, h3 };
House h4;
h4=getBigger(arr, 3);
h4.print();
system("pause");
return 0;
}
I have problem with my program for building and a house. It is simple maybe but I don't know why throws exception. I think that my try for user input is wrong anywhere.
Your Building constructors both set address to null. If you are trying to print the address anywhere, your code will give you that error.

Crashing when objects are deleted

It's crashing at the very end of the main() function where it needs to delete the starters objects. The error message that pops up when I run the program says: Debug assertion failed! Expression: _BLOCK_IS_VALID(pHead->nBlockUse). How do i fix it from crashing when deleting the starters objects?
#include <iostream>
#include <fstream>
#include "olympic.h"
using namespace std;
ofstream csis;
int main() {
const int lanes = 4;
Ranker rank(lanes);
csis.open("csis.txt");
// First make a list of names and lane assignments.
Competitor* starters[lanes];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
// The race is run; now assign a time to each person.
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
// Put everyone into the ranker.
for (int i = 0; i < lanes; i++)
rank.addList(starters[i]);
// Now print out the list to make sure its right.
cout << "Competitors by lane are:" << endl;
csis << "Competitors by lane are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
// Finally, show how they finished.
cout << "Rankings by finish are:" << endl;
csis << "Rankings by finish are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for (int i = 0; i < lanes; i++)
delete starters[i];
csis.close();
}
ranker.cpp:
#include "ranker.h"
#include "competitor.h"
#include <stdlib.h>
Ranker::Ranker(int lanes) {
athlete = new Competitor*[lanes];
numAthletes = 0;
maxAthletes = lanes;
}
int Ranker::addList(Competitor* starter) {
if (numAthletes < maxAthletes && starter != NULL) {
athlete[numAthletes] = starter;
numAthletes++;
return numAthletes;
}
else
return 0;
}
Competitor* Ranker::getLane(int lane) {
for (int i = 0; i < numAthletes; i++) {
if (athlete[i]->getLane() == lane) {
return athlete[i];
}
}
return NULL;
}
Competitor* Ranker::getFinish(int position) {
switch(position) {
case 1:
return athlete[3];
break;
case 2:
return athlete[2];
break;
case 3:
return athlete[1];
break;
case 4:
return athlete[0];
break;
}
return NULL;
}
int Ranker::getFilled() {
return numAthletes;
}
Ranker::~Ranker() {
delete [] athlete;
}
competitor.h:
#ifndef _COMPETITOR_H
#define _COMPETITOR_H
class Competitor {
private:
char* name;
int lane;
double time;
public:
Competitor(char* inputName, int inputLane);
Competitor();
void setTime(double inputTime);
char* getName();
int Competitor::getLane();
double getTime();
void print();
~Competitor();
};
#endif
competitor.cpp:
#include "competitor.h"
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
Competitor::Competitor(char* inputName, int inputLane) {
name = inputName;
lane = inputLane;
}
Competitor::Competitor() {
name = 0;
lane = 0;
time = 0;
}
void Competitor::setTime(double inputTime) {
time = inputTime;
}
char* Competitor::getName() {
return name;
}
int Competitor::getLane() {
return lane;
}
double Competitor::getTime() {
return time;
}
void Competitor::print() {
cout << setw(20) << name << setw(20) << lane << setw(20) << setprecision(4) << time << endl;
}
Competitor::~Competitor() {
delete [] name;
}
Call stack:
before crash: http://i.imgur.com/d4sKbKV.png
after crash: http://i.imgur.com/C5cXth9.png
After you've added Competitor class, it seems the problem is that you delete its name in Competitor's destructor. But you assign it from string literal which can't really be deleted. I'm sure the stack trace leading to assertion will prove that.
One way of solving the problem would be using std::string to store the name.
Problem is when deleting the char* value on destructor, which is assigned with const char instead new char. So i have slightly changed the constructor to copy the const char to new char.
Competitor::Competitor(char* inputName, int charlen, int inputLane)
{
name = new char[charlen + 1];
memcpy(name , inputName, charlen );
name [charlen] = '\0';
lane = inputLane;
}