Originally, my lab was passing three argument: addFractionJesseR(*lFrac, *rFrac, **resFrac); but I just found out I can't pass three arguments. I had to change it to **resFrac = addFractionJesseR(*lFrac, *rFrac); and now I'm having problems compiling. I know my pointers and double pointers are out of scope somewhere but I just can't spot where. the debugger points to the second line as the problem:
FractionJesseR& FractionJesseR::operator=(const FractionJesseR& arg) {
num = arg.num;
denom = arg.denom;
return *this;
}
which is called by:
FractionJesseR& addMenu(FractionJesseR* lFrac, FractionJesseR* rFrac) {
int option;
FractionJesseR** resFrac = new FractionJesseR*();
......
case 2:
cout << "Calling add() --\n\n";
**resFrac = addFractionJesseR(*lFrac, *rFrac);
break;
......
**resFrac = addFractionJesseR(*lFrac, *rFrac); was originally addFractionJesseR(*lFrac, *rFrac, **resFrac);
which is called by:
void displayMenu() {
int option;
FractionJesseR *lFrac = nullptr;
FractionJesseR *rFrac = nullptr;
FractionJesseR *resFrac = nullptr;
......
case 2:
cout << " Adding Option --\n\n";
if (lFrac == nullptr && rFrac == nullptr) {
cout << " Not a proper call as no Fractions are available!\n\n";
}
else {
*resFrac = addMenu(lFrac, rFrac);
}
break;
*resFrac = addMenu(lFrac, rFrac) was originally addMenu(lFrac, rFrac, &resFrac)
(yes, I did call delete on all my pointers, I'm still new to Stack Overflow and learning to only put up relevant snippets of code) I need help pointing me in the right direction. I think my pointers go out of scope somewhere in addMenu or displayMenu... maybe I'm dereferencing a double pointer wrong?
Any help would be greatly appreciated!
edit:
FractionJesseR& addFractionJesseR(FractionJesseR& lFrac, FractionJesseR& rFrac) {
int n = 0;
int d = 0;
FractionJesseR *resFrac = nullptr;
// Adding the fractions
n = (&lFrac)->getNum() * (&rFrac)->getDenom() + (&lFrac)->getDenom() *
(&rFrac)->getNum();
d = (&lFrac)->getDenom() * (&rFrac)->getDenom();
resFrac = new FractionJesseR(n / gcd(n, d), d / gcd(n, d));
if (d < 0) {
d = -d;
n = -n;
}
return *resFrac;
}
You're having issues with memory management.
I assume you are using some version of Visual Studio. The debugger will usually mark the next line to be executed, so you're getting a crash on
num = arg.num;
This happens because this
is null, since
FractionJesseR** resFrac = new FractionJesseR*();
allocates a pointer on the free store (which is unusual) and initializes it with 0 (because of the brackets). This:
**resFrac
first dereferences resFrac
, giving a null pointer, which you then dereference again. Dereferencing a null pointer is undefined behaviour. In your case, it causes a crash in the assignment operator on the first statement.
The obvious solution is to stop using pointers and manual memory management. At best, use objects:
FractionJesseR resFrac
// ...
resFrac = addFractionJesseR(*lFrac, *rFrac);
At worst, use smart pointers:
auto resFrac = std::make_unique<FractionJesseR>();
// ...
*resFrac = addFractionJesseR(*lFrac, *rFrac);
What you don't want to do (unless you are forced to because this is an assignment, in which case I'd question the motivation):
auto resFrac = new FractionJesseR;
// ...
*resFrac = addFractionJesseR(*lFrac, *rFrac);
// ...
delete resFrac;
addFractionJesseR()
is returning a reference to a value that was allocated on the free store. Where are you going to delete it? Every new
must be matched with a delete
.
If you really want an example of manual memory management, you should not mix pointers and references:
FractionJesseR* addFractionJesseR(FractionJesseR* a, FractionJesseR* b)
{
auto n = a->getNum() * b->getDenom() + a->getDenom() * b->getNum();
auto d = a->getDenom() * b->getDenom();
if (d < 0)
{
d = -d;
n = -n;
}
return new FractionJesseR(n / gcd(n, d), d / gcd(n, d));
}
FractionJesseR* addMenu(FractionJesseR* a, FractionJesseR* b)
{
// ...
FractionJesseR* resFrac = addFractionJesseR(a, b);
// ...
return resFrac;
}
void displayMenu()
{
// ...
FractionJesseR *resFrac = addMenu(lFrac, rFrac);
// ...
delete resFrac;
}
Notice that the pointer allocated in addFractionJesseR()
is returned to addMenu()
, which returns it to displayMenu()
, which deletes it.