I've been writing a program to simulate a paging system for an assignment. The program almost works but for some reason I'm getting a segfault when I try to delete my dynamically allocated array of frames.
Here's the algorithm code:
int main(int argc, char* argv[])
{
// Initialize page count
PageCount = 0;
// Validate input
ValidateArgs(argc, argv);
// Load programs and trace from list file
Programs = LoadPrograms();
Trace = LoadTrace();
// Load main memory
MainMemory Memory = MainMemory(Programs);
// Run the Algorithm
Run(Memory);
// Print results
Print();
// Print the output to a file
PrintOutput();
return 0;
}
void Run(MainMemory memory)
{
int page, frame;
vector<int> replaceFrame;
for (long i = 0; i < Trace.size(); i++)
{
// Get page and frame
page = Programs[Trace[i].ProgramNum].GetPage(Trace[i].Word);
frame = memory.IsInMemory(page);
if (frame != -1)
{
// Access page
memory.Frames[frame].Access(i);
}
else
{
// Find page to replace
if (Algorithm == "clock")
{
replaceFrame = memory.FindClock();
}
else if (Algorithm == "lru")
{
replaceFrame = memory.FindLRU(i);
}
else
{
replaceFrame = memory.FindOldest(i);
}
// Replace page
memory.Frames[replaceFrame[0]].Replace(page, i);
// Replace with next contiguous page for prepaging
if (HowToPage)
{
memory.Frames[replaceFrame[1]].Replace(
Programs[Trace[i].ProgramNum].GetNextPage(
Trace[i].Word), i);
}
}
}
return;
}
Program and Request are both data types loaded from files. Request is just a data struct and Program has a vector of ints as one of its members.
At the end of this function, my MainMemory object (the one that contains the dynamically allocated array) calls its destructor which is in my MainMemory struct:
struct MainMemory
{
Frame* Frames;
int Number;
// Initializes an object of the MainMemory class
MainMemory(vector<Program> thePrograms)
{
Number = MemorySize / PageSize;
Frames = new Frame[Number];
int numberProgs = thePrograms.size(), counter = 0;
// Load main memory
for (int i = 0; i < numberProgs; i++)
{
for (int j = 0; j < thePrograms[i].Pages.size(); j++)
{
int page = thePrograms[i].Pages[j];
Frames[counter] = Frame(page, 0);
if (counter + 1 < Number)
{
counter++;
}
else
{
return;
}
}
}
}
// Initializes an object of the MainMemory class with another object
// of the MainMemory class
MainMemory(const MainMemory& cpy)
{
*this = cpy;
}
// Sets one MainMemory equal to another
MainMemory& operator=(const MainMemory& rhs)
{
Number = rhs.Number;
Frames = new Frame[Number];
for (int i = 0; i < Number; i++)
{
Frames[i] = Frame(rhs.Frames[i].Number,
rhs.Frames[i].TimeStamp, rhs.Frames[i].UseCount,
rhs.Frames[i].UseBit);
}
return *this;
}
// Deletes the MainMemory object
~MainMemory()
{
delete[] Frames;
Frames = NULL;
}
};
After some testing, I know that the Frames object has a memory address coming in to the destructor. Further, the code fails at the line indicated. The Frame struct doesn't have any dynamic elements so I didn't bother creating a destructor for it and instead let C++ do that for me.
struct Frame
{
int Number;
int TimeStamp;
int UseCount;
bool UseBit;
// Initializes an empty object of the Frame class
Frame() { }
// Initializes an object of the Frame class
Frame(int number, int time)
{
Number = number;
TimeStamp = time;
UseCount = time;
UseBit = false;
}
// Initializes an object of the Frame class
Frame(int number, int time, int count, bool use)
{
Number = number;
TimeStamp = time;
UseCount = count;
UseBit = use;
}
// Simulates a replacement of one frame with a page from secondary
void Replace(int page, int time)
{
Number = page;
TimeStamp = time;
UseCount = time;
UseBit = true;
PageFaults++;
return;
}
// Simulates a memory access to the frame
void Access(int time)
{
UseCount = time;
UseBit = true;
return;
}
};
But clearly, something's not working so I'm wondering where I screwed up.
Thanks for your help!
EDIT: I rechecked my constructor to see if it was shallow-copying anything. All elements in the copied element were in different locations from the original.
EDIT: I've been asked to add a SSCCE to this post:
int main(int argc, char* argv[])
{
PageCount = 0;
Programs = LoadPrograms();
Trace = LoadTrace();
MainMemory Memory(Programs);
cout << endl << "Running algorithm" << endl;
cout << endl << "Memory is at location " << &Memory << endl;
Test(Memory);
return 0;
}
void Test(MainMemory memory)
{
cout << endl << "Memory at location " << &memory << endl;
return;
}
This is the output I get:
Running algorithm
Memory is at location 0x7fff910a4eb0
Memory at location 0x7fff910a4ec0
In destructor
Frames in 0x7fff910a4ec0
Frames deleted
Destruction finished
It's copying correctly at least. Further, after changing the copy constructor, to explicitly copy the object (thanks Joachim Pileborg), it almost finishes executing Run(). However, there's still a problem with deallocating the memory. So, I think the issue is with the Run() function itself.