sanjam
sanjam

Reputation: 1

Debug Assertion failed c++

I am working on my homework. Aim is to implement class for operations over large integers(BigInt).

Initialization: each object of class BigInt is constructed as a dynamical array. Members of array are digits of a string entered by user (in reversed order - it was easier for me this way to implement operations).

Specifications of class BigInt: relations between two BigInts (less, greater, equal), operations: addition, subtraction, multiplication. Relations, addition and subtraction work well. Problem is with multiplication.

Problem: when I test the program without multiplication, it works well. When I uncomment multiplication, program breaks after it writes the result of relations, addition and subtraction.

Error: debug assertion failed. When I enter Debug mode, I see that it calculates well until the line:

DELETE [] m;

I looked other questions about debug assertion, and realised that I can't delete object of class BigInt with delete[] m, because I already wrote that in my destructor. I tried with DELETE m. When I do that, it prints out good result, but it breaks after the line:

 cout << "before returing m" << endl;. 

Error: again Debug Assertion failed, but this time added:

L buffer is too small.

When I enter Debug mode, it shows me that the breakpoint is in Deep Copy constructor, line:

strcpy_s(myDigits, myNumDigits, source.myDigits);

Now I don't know what to do, because it worked well with addition and subtraction (but I guess that in these operations deep copy constructor was never used).

So, the question I need answer to: where is a mistake, is it with using delete[], delete or in implementation of deep copy constructor (or somewhere else)?

I am attaching my code. I don't want it to be difficult to review, so I will attach only the parts needed for the solution of my problem (part of code with constructors, destructor, multiplication). If you think that I should attach more, please tell me in comment.

Construction/Destruction:

    BigInt::BigInt(string digits)
{
    const char* s = digits.c_str();
    int k;
    int limit = 0;
    myNumDigits = 0;
    if (strlen(s) == 0) 
    {
        mySign = positive;
        //myDigits = new char[2];
        myDigits = nullptr;
        myNumDigits = 0;
        cout << "Empty string!" << endl;
        return;
    }
    if (digits[0] == '-')
    {
        mySign = negative;
        limit = 1;
    }
    else
    {
        mySign = positive;
        if (digits[0] == '+')
            limit = 1;
    }
    const char*help = digits.c_str();
    myDigits = new char[strlen(s) + 1 - limit];
    // reversed order
    for (k = strlen(help) - 1; k >= limit; k--)
    {
        if (!isdigit(digits[k]))
        {
            cout << "onlu digits and sign! " << endl;
            exit(1);
        }
        AddSigDigit(digits[k] - '0');   //incrementation
    }
    myDigits[strlen(s) - limit] = '\0';
}

// Copy constructor -deep
BigInt::BigInt(const BigInt& source)
{
    // can do shallow copy of a number
    myNumDigits = source.myNumDigits;

    //deep copy of array
    if (source.myDigits)
    {
        myDigits = new char[myNumDigits + 1];
        strcpy_s(myDigits, myNumDigits, source.myDigits); //BREAKPOINT!!!!!
        myDigits[myNumDigits] = '\0';
    }
    else
        myDigits = 0;
}
// move copy constructor 
BigInt::BigInt(BigInt&&other) {

    myNumDigits = other.myNumDigits;
    myDigits = other.myDigits;  
    other.myNumDigits = 0;
    other.myDigits = 0;//null pointer
}
BigInt::BigInt(Sign sign, int NumDig, char* sum) {
    mySign = sign;
    myNumDigits = NumDig;
    myDigits = sum;
    sum = 0;
}
BigInt::~BigInt() {
    delete[] myDigits;
}

Help functions:

int BigInt::GetDigit(int k) const

{
    if (0 <= k && k < NumDigits())
    {
        return myDigits[k] - '0';
    }
    return 0;
}
void BigInt::AddSigDigit(int value)
// adding value on place of most significant digit
{
    myDigits[myNumDigits] = '0' + value;
    myNumDigits++;
}

Multiplication:

BigInt BigInt::mul(const BigInt&num)const {

char* a =new char[num.myNumDigits+1];
strcpy(a, num.myDigits);
a[num.myNumDigits] = '\0';
cout << "a" << a << endl;
char* b = new char[myNumDigits + 1];
strcpy(b,myDigits);
b[myNumDigits] = '\0';
cout << "b" << b << endl;
string temp;
BigInt* m = new BigInt("0");
//cout << *m << endl;
unsigned int i;
for ( i = 0; i < strlen(a); i++) {
int carry = 0;
temp = string (i, '0');
unsigned int j;
for (j = 0; j < (int)strlen(b); j++) {
    int pom;
    pom = (a[i] - '0') * (b[j] - '0') + carry;
    temp += ((char)(pom % 10 + '0'));
    carry = pom / 10;
}

if (carry != 0) 
    temp += (carry + '0');
cout <<"temp unreversed in i. iteration" <<temp<<"  " <<i << endl;
reverse(temp.begin(), temp.end());
cout << "temp reversed in  i. iteration" << temp << "  " << i << endl;
BigInt* n = new BigInt((*m).add(BigInt(temp.substr(cut(temp)))));
std::cout << "n in i. iteration  " << *n<<"i."<<i<<endl;
delete m;
std::cout << " delete pass" << endl;
m = n;
n = nullptr;
}
cout << "before returing m" << endl;
return (*m); //BECAUSE OF THIS LINE THERE IS BREAKPOINT IN COPY CONSTRUCTOR
cout << "after returing m" << endl;
}

int BigInt::cut(const string& i)const {
int index = 0;
while (i[index] == '0' && index < i.size() - 1) index++;
return index;
}

Upvotes: 0

Views: 185

Answers (1)

user58697
user58697

Reputation: 7923

The mul code creates m once, and deletes it in the loop. Welcome to UB.

Upvotes: 1

Related Questions