std::make_unique<bool[]>(x) is giving me malloc(): invalid size (unsorted) error

584 views Asked by At
  1. I am trying to create a Bool Array class which takes a string of integers and converts them into bool arrays. Once I have 2 Bool Array variables I perform Karatsuba Multiplication.

Below is where the actual error arises from.

explicit BoolArray(BoolArray const &ref, int start) : dimensions_{ref.dimensions_-1} {
                //std::cout << ref << std::endl;
                //std::cout << "Start" << std::endl;
                //std::cout << ref.dimensions_-1 << std::endl;
                //std::cout << dimensions_ << std::endl;
                //std::cout << start << std::endl;
                sign_ = false;
                //std::cout << "Make_unique" << std::endl;
                arr_ = std::make_unique<bool[]>(dimensions_); //Line doesn't run in some cases
                //std::cout << "Make_unique Accomplished" << std::endl;
                std::memcpy(arr_.get(),ref.arr_.get()+start,dimensions_*sizeof(bool));
                //std::cout << *this << std::endl;
            }

These are my private variables.

mutable unsigned int dimensions_;
mutable std::unique_ptr<bool[]> arr_;

I used GDB to find out where the error was occurring, and it pointed to this specific function call. I then use print statements to determine what exact line wasn't running and it was the make_unique line.

Now the interesting bit here is, say I were to multiply a 5000 digit number by a 5000 digit number. It's first converted to a bool array occurs. It is then multiplied, the multiplication occurs perfectly and it returns another bool array.

In the case of 13000 digits however, when multiplying them together I specifically get the error: malloc(): invalid size (unsorted) error.

Now, I'm not expecting someone to debug this but I am looking for reasons why std::make_unique<bool []>(x), could break?

Thank you

Edit: I have just used valgrind and I seem to be getting many ==14286== Invalid read of size 1 ==14286== Invalid write of size 1 , but the output I was getting has been fine so far. I even tried this for simple multiplication between 1 and 1. And I'm getting quite a bit of errors with valgrind, but I thought it was just running smoothly though. Edit:

I think what's been causing the errors so far have been this specific function. Please note that, the else statement is basically the code reused (I know I can also do this without the if statement), but using the code below I am getting the valgrind errors, which I will copy paste below.

 friend BoolArray operator+(BoolArray &x, BoolArray  &y) {
                if (x.size() <= y.size()) {
                    int max = y.size();
                    int min = x.size();
                    int mSize = max;
                    auto ret = BoolArray(++mSize);
                    bool remainder = 0;

                    for (; min >= 0; --min) {
                        ret[mSize] = output_[remainder][ y[max] ][x[min] ];
                        remainder = carry_[remainder][ y[max] ][ x[min] ];
                        --max;
                        --mSize;
                    }
                    
                    for (; max >= 0; --max) {
                        ret[mSize] = output_[remainder][ y[max] ][ 0 ];
                        remainder = carry_[remainder][ y[max] ][ 0 ];
                        --mSize;
                    }

                    if (remainder) {
                        ret[mSize] = 1;
                    } else {
                        auto newRet = BoolArray(ret,1);
                        return newRet;
                    }
                    return ret;

Valgrind Error

==14457== Invalid read of size 1
==14457==    at 0x10BABA: BigNum::operator+(BigNum::BoolArray&, BigNum::BoolArray&) (DataStructure.cpp:422)
==14457==    by 0x10A65A: main (DataStructure.cpp:693)
==14457==  Address 0x4da8f52 is 0 bytes after a block of size 2 alloc'd
==14457==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==14457==    by 0x10C26F: std::_MakeUniq<bool []>::__array std::make_unique<bool []>(unsigned long) (unique_ptr.h:863)
==14457==    by 0x10AB46: BigNum::BoolArray::BoolArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (DataStructure.cpp:58)
==14457==    by 0x10A5CD: main (DataStructure.cpp:688)
==14457==
==14457== Invalid read of size 1
==14457==    at 0x10BAD9: BigNum::operator+(BigNum::BoolArray&, BigNum::BoolArray&) (DataStructure.cpp:422)
==14457==    by 0x10A65A: main (DataStructure.cpp:693)
==14457==  Address 0x4da8dc2 is 0 bytes after a block of size 2 alloc'd
==14457==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==14457==    by 0x10C26F: std::_MakeUniq<bool []>::__array std::make_unique<bool []>(unsigned long) (unique_ptr.h:863)
==14457==    by 0x10AB46: BigNum::BoolArray::BoolArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (DataStructure.cpp:58)
==14457==    by 0x10A57F: main (DataStructure.cpp:687)
==14457==
==14457== Invalid write of size 1
==14457==    at 0x10BB19: BigNum::operator+(BigNum::BoolArray&, BigNum::BoolArray&) (DataStructure.cpp:422)
==14457==    by 0x10A65A: main (DataStructure.cpp:693)
==14457==  Address 0x4da93e3 is 0 bytes after a block of size 3 alloc'd
==14457==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==14457==    by 0x10C26F: std::_MakeUniq<bool []>::__array std::make_unique<bool []>(unsigned long) (unique_ptr.h:863)
==14457==    by 0x10ADAF: BigNum::BoolArray::BoolArray(unsigned int const&) (DataStructure.cpp:72)
==14457==    by 0x10BA8A: BigNum::operator+(BigNum::BoolArray&, BigNum::BoolArray&) (DataStructure.cpp:418)
==14457==    by 0x10A65A: main (DataStructure.cpp:693)
==14457==
==14457== Invalid read of size 1
==14457==    at 0x10BB3C: BigNum::operator+(BigNum::BoolArray&, BigNum::BoolArray&) (DataStructure.cpp:423)
==14457==    by 0x10A65A: main (DataStructure.cpp:693)
==14457==  Address 0x4da8f52 is 0 bytes after a block of size 2 alloc'd
==14457==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==14457==    by 0x10C26F: std::_MakeUniq<bool []>::__array std::make_unique<bool []>(unsigned long) (unique_ptr.h:863)
==14457==    by 0x10AB46: BigNum::BoolArray::BoolArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (DataStructure.cpp:58)
==14457==    by 0x10A5CD: main (DataStructure.cpp:688)
==14457==
==14457== Invalid read of size 1
==14457==    at 0x10BB5B: BigNum::operator+(BigNum::BoolArray&, BigNum::BoolArray&) (DataStructure.cpp:423)
==14457==    by 0x10A65A: main (DataStructure.cpp:693)
==14457==  Address 0x4da8dc2 is 0 bytes after a block of size 2 alloc'd
==14457==    at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==14457==    by 0x10C26F: std::_MakeUniq<bool []>::__array std::make_unique<bool []>(unsigned long) (unique_ptr.h:863)
==14457==    by 0x10AB46: BigNum::BoolArray::BoolArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (DataStructure.cpp:58)
==14457==    by 0x10A57F: main (DataStructure.cpp:687)
==14457==
10 <- This is my output.

The code I am running which calls the + overload

    auto m1 = BigNum::BoolArray("1"); //[01]
    auto m2 = BigNum::BoolArray("1"); //[01]

    std::cout << m1.size() << std::endl;
    std::cout << m2.size() << std::endl;

    std::cout << m1 + m2 << std::endl; //[10]

So, now I think I need to figure out why the + overload is giving me these specific errors..

1

There are 1 answers

0
Steveit On

I have edited my code, so it turns out Remy was right that I have corrupted memory beforehand by accessing stuff that I was not meant to be as my operator overloads for [] were poorly written so I did not realise I was going out of bounds. So I had to adjust the code in my + operator overload. int max = y.size();

                    int mSize = max+1;
                    max--;
                    int min = x.size();
                    min--;
                    auto ret = BoolArray(mSize);
                    mSize--;
                    bool remainder = 0;

TO something like that, I know its very ugly but gets the job done. Anyone thank you, but at the same time I'd like to know this would specifically affect whats happening with the make_unique function.