Thread: C++ Binary Adder Error on exit

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    25

    Question C++ Binary Adder Error on exit

    I have been having some difficulty with one of my first more complex C++ programs. The program adds the input as I would expect, the problem is when I give it the quit command, it works fine in Netbeans, but when I test it on a slightly older Unix environment, where it gets tested, I get the following output before it terminates:

    *** glibc detected *** ./a.out: free(): invalid pointer: 0x09bf8050 ***======= Backtrace: =========
    /lib/i386-linux-gnu/libc.so.6(+0x73e42)[0x190e42]
    /usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0x7dd51f]
    /usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1b )[0x7c499b]
    /usr/lib/i386-linux-gnu/libstdc++.so.6(+0x909dc)[0x7c49dc]
    /usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs7reserveEj+0x88)[0x7c5c38]
    /usr/lib/i386-linux-gnu/libstdc++.so.6(_ZNSs6appendEPKcj+0xe8)[0x7c5f88]
    /usr/lib/i386-linux-gnu/libstdc++.so.6(_ZStrsIcSt11char_traitsIcESaIcEERSt 13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_E+0x1ae)[0x78cbce]
    ./a.out[0x8049190]
    /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x1364d3]
    ./a.out[0x8048a51]
    ======= Memory map: ========
    0011d000-002bc000 r-xp 00000000 08:01 273146 /lib/i386-linux-gnu/libc-2.15.so
    002bc000-002be000 r--p 0019f000 08:01 273146 /lib/i386-linux-gnu/libc-2.15.so
    002be000-002bf000 rw-p 001a1000 08:01 273146 /lib/i386-linux-gnu/libc-2.15.so
    002bf000-002c2000 rw-p 00000000 00:00 0
    002c2000-002ec000 r-xp 00000000 08:01 273150 /lib/i386-linux-gnu/libm-2.15.so
    002ec000-002ed000 r--p 00029000 08:01 273150 /lib/i386-linux-gnu/libm-2.15.so
    002ed000-002ee000 rw-p 0002a000 08:01 273150 /lib/i386-linux-gnu/libm-2.15.so
    004bb000-004bc000 r-xp 00000000 00:00 0 [vdso]
    00734000-0080c000 r-xp 00000000 08:01 392018 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
    0080c000-0080d000 ---p 000d8000 08:01 392018 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
    0080d000-00811000 r--p 000d8000 08:01 392018 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
    00811000-00812000 rw-p 000dc000 08:01 392018 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
    00812000-00819000 rw-p 00000000 00:00 0
    00850000-00870000 r-xp 00000000 08:01 273143 /lib/i386-linux-gnu/ld-2.15.so
    00870000-00871000 r--p 0001f000 08:01 273143 /lib/i386-linux-gnu/ld-2.15.so
    00871000-00872000 rw-p 00020000 08:01 273143 /lib/i386-linux-gnu/ld-2.15.so
    00da5000-00dc1000 r-xp 00000000 08:01 276654 /lib/i386-linux-gnu/libgcc_s.so.1
    00dc1000-00dc2000 r--p 0001b000 08:01 276654 /lib/i386-linux-gnu/libgcc_s.so.1
    00dc2000-00dc3000 rw-p 0001c000 08:01 276654 /lib/i386-linux-gnu/libgcc_s.so.1
    08048000-0804a000 r-xp 00000000 00:18 33294022 /home/awh0045/CSE 2100/Program 1/a.out
    0804a000-0804b000 r--p 00001000 00:18 33294022 /home/awh0045/CSE 2100/Program 1/a.out
    0804b000-0804c000 rw-p 00002000 00:18 33294022 /home/awh0045/CSE 2100/Program 1/a.out
    09bf8000-09c19000 rw-p 00000000 00:00 0 [heap]
    b76eb000-b76ee000 rw-p 00000000 00:00 0
    b76ff000-b7704000 rw-p 00000000 00:00 0
    bf8f3000-bf914000 rw-p 00000000 00:00 0 [stack]
    Aborted (core dumped)

    I have been at a loss as far as fixing this. From my reading so far through others, it has to do with a memory leak. The only thing that I could think would possibly be responsible would be the dynamic int arrays in my program. Right now I haven't designed a specific destructor, but if anyone has some tips to get me headed in the right direction, I would greatly appreciate it.

    For how the program works, it works as follows:

    user inputs:

    ripple_carry/> add 101 11
    1000
    ripple_carry/> add -212 1
    Error! Number is not binary.
    ripple_carry/> add -101 11
    Error! Number is negative.
    ripple_carry/> add 11000 1000
    Error! Overflow.
    ripple_carry/>quit
    [Program Terminates]

    Here's the source code:

    Binary.h: Class Defined

    Code:
    #include <string>
    
    using namespace std;
    
    
    class Adder {
    
    
    private:
        int MaxSize; //maximum number of bits.
    public:
        Adder(int); //constructor
            ~Adder();
            string oper, num1, num2;
            int *Num1, *Num2, *Result;
            int OF, Neg, Bin; //error checking values
            void Add(); 
            int Choice(string);
            void StoInt();
            void print();
            void Clear();
            void Initialize_Arrays();
        
    };
    Binary.cpp:Functions declared

    Code:
    #include "Binary.h"#include <iostream>
    #include <sstream>
    using namespace std;
    
    
    Adder::Adder(int x) {
    
    
        MaxSize = x;
    }
    
    
    Adder::~Adder() { }
    
    
    void Adder::Add() {
        OF=0;
        int i = MaxSize-1; //start at position 4
        int k = MaxSize-2; // start at position 3
    
    
        while (i > 0) {
    
    
            Result[i] += (Num1[i] + Num2[i]);
    
    
            if (Result[i] > 1) {
                Result[i] -= 2; // subtract 2
                Result[k]++; // carry bit over to next place.
            }
            i--; // decrease both counters.
            k--;
    
    
        }
        Result[i] += Num1[i] + Num2[i]; // do one last time for position 0.
    
    
        if (Result[i] > 1) OF = 1; // if result[0] is 2 or more, then overflow is true.
    
    
        delete[] Num1;
        delete[] Num2;
    
    
    }
    
    
    int Adder::Choice(string c) {
    
    
        int choice = 0;
        if (c == "add") choice = 1;
        else
            if (c == "quit") choice = 2;
            else choice = 3; // number for choice undefined.
    
    
    
    
        return choice;
    }
    
    
    void Adder::StoInt() {
    
    
    
    
    
    
        Bin=1;
    
    
        int k = 0;
        int num1Size = num1.length(); //length of first input
        int num2Size = num2.length(); //length of second input
        int startPoint_n1 = (MaxSize - num1Size);
        int startPoint_n2 = (MaxSize - num2Size);
    
    
        for (int i = startPoint_n1; i < MaxSize; i++) {
    
    
            if (num1[k] == '1') Num1[i] = 1;
               else if (num1[k] == '0') Num1[i] = 0;
               else Bin = 0; // if not a 1 or 0, then it's not binary.
            k++;
    
    
        }
        k=0;
        for(int i = startPoint_n2; i<MaxSize; i++)
        {
            if(num2[k] == '1') Num2[i] = 1;
               else if(num2[k] == '0') Num2[i] = 0;
                   else Bin=0;
            k++;
        }
    
    
        
    
    
    
    
    
    
    }
    
    
    void Adder::Initialize_Arrays() {
        //Allocate space for arrays needed in future steps.
        Num1 = new int[MaxSize];
        Num2 = new int[MaxSize];
        Result = new int[MaxSize];
        //-----------------------------
    }
    
    
    void Adder::print() {
    
    
        int j;
        for(j=0; j<MaxSize; j++)
        {
            if(Result[j] >0) break;
        }
        
        
        for (int i = j; i < MaxSize; i++) {
    
    
            cout << Result[i]; // prints out from left to right.
    
    
        }
        cout << endl;
        
        delete[] Result;
    
    
    }
    
    
    void Adder::Clear() {
        // clear arrays with zeros to prevent previous data from corrupting.
        for (int i = 0; i < 6; i++) {
            Num1[i] = 0;
            Num2[i] = 0;
            Result[i] = 0;
        }
    
    
    }
    Main.cpp: Controls program flow.

    Code:
    #include <cstdlib>#include <iostream>
    #include "Binary.h"
    #include <string>
    #include <sstream>
    using namespace std;
    
    
    /*
     * 
     */
    int main() {
    
    
        int choice = 0;
        Adder bin(5);
        
        string input;
        int op;
         //Allocating space for int arrays.
        while (true) {
    
    
            cout << "ripple_carry> ";
            getline(cin, input);
            istringstream ss(input); //taking input, and breaking into commands.
            ss >> bin.oper;
    
    
            if (bin.Choice(bin.oper) == 3) {
    
    
                cout << "Error! Not a valid command." << endl;
                continue;
    
    
            }
            if (bin.Choice(bin.oper) == 2) break;
    
    
            if (bin.Choice(bin.oper) == 1) {
                bin.Initialize_Arrays();
                ss >> bin.num1;
                ss >> bin.num2;
                if (bin.num1.length() > 5 || bin.num2.length() > 5) {
    
    
                    cout << "Error! Number exceeds 5 bits!" << endl;
                    continue;
    
    
                }
    
    
                if (bin.num1[0] == '-' || bin.num2[0] == '-') {
                    cout << "Error! Number is negative." << endl;
                    continue;
                }
                
                bin.Clear();
    
    
                bin.StoInt(); //converting string to int array.
    
    
                if (bin.Bin > 0) {
                    bin.Add();
                    if (bin.OF < 1) {
                        bin.print();
                    }
                    if (bin.OF == 1) {
                        cout << "Error! Overflow." << endl;
                        continue;
                    }
                }
                if (bin.Bin == 0) {
                    cout << "Error! Number not Binary." << endl;
                }
    
    
    
    
    
    
    
    
    
    
            }
    
    
    
    
    
    
    
    
    
    
        }//while
        
        
        return 0;
        
    }//main

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > for (int i = 0; i < 6; i++)
    Why is this 6, and not maxSize ?

    Why does your destructor not do anything?

    Why does your main have 20 blank lines in it?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2011
    Posts
    25
    Sorry about the surplus blank lines, I fixed those with Notepad++, but is there a tool like TextFX that can do that in Netbeans?

  4. #4
    Registered User
    Join Date
    Sep 2011
    Posts
    25
    Just put in the destructor, it works! thank you for pointing me in the right direction.

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by alexhollis View Post
    Just put in the destructor, it works! thank you for pointing me in the right direction.
    Although a destructor is a good idea, the actual bug was the hard-coded 6 in Adder::Clear, which should instead be MaxSize as Salem said.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    • The destructor should be deleting Num1, Num2, and Result
    • Add should not be deleting Num1 or Num2 (and leaving dangling pointers)
    • print should not be deleting Result (and leaving a dangling pointer)
    • Initialize_Arrays should be removed and the allcoations done from within the constructor
    • For true/false flag type of variablesdon't use int, C++ has a bool type, which should be used for those
    • Member functions which read, but do not modify member variables should be marked as const
    • Member functions which do not use member variables at all should be marked as static
    • Pass strings by const-reference, and learn to use constructor initialisation lists
    • "OF" is a bad variable name for multiple reasons. You might accidentally type a zero and since 0f is a valid float literal you would get a very confusing error message. "overflow" would be better.
    • Currently your class provides an automatically generated copy-constructor and assignment-operator. You must either prevent these being generated by declaring them private and leaving them unimplemented, or you must implement these. IMHO any class that allows broken automatically generated versions of these to exist is itself broken. Read up about the Rule of Three.
    • Your main is too long. Firstly remove the excess whitespace. One blank line between certain lines can be strategically used for emphasis, but beyond that it is just a waste of space. Then if it still wont all fit on screen at once, consider moving some of it into its own function
    Last edited by iMalc; 09-21-2012 at 04:53 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simulating an Adder
    By threwup in forum C Programming
    Replies: 2
    Last Post: 02-10-2011, 11:17 AM
  2. need help with hex adder.
    By webznz in forum C Programming
    Replies: 5
    Last Post: 03-24-2008, 11:10 PM
  3. Exit error
    By skiler in forum C++ Programming
    Replies: 15
    Last Post: 01-09-2008, 09:38 AM
  4. Program Terminating With Error On Exit
    By chriscolden in forum C Programming
    Replies: 19
    Last Post: 01-14-2006, 04:40 AM

Tags for this Thread