Deallocating memory - c++

For a project I have to implement a bitset class. My code thus far is:
Header File
#ifndef BITSET_H_
#define BITSET_H_
#include <string>
#include <cmath>
using namespace std;
// Container class to hold and manipulate bitsets
class Bitset {
public:
Bitset();
Bitset(const string);
~Bitset();
// Returns the size of the bitset
int size();
// Sets a bitset equal to the specified value
void operator= (const string);
// Accesses a specific bit from the bitset
bool operator[] (const int) const;
private:
unsigned char *bitset;
int set_size;
// Sets a bitset equal to the specified value
void assign(const string);
};
#endif /* BITSET_H_ */
Source File
#include "bitset.h"
Bitset::Bitset() {
bitset = NULL;
}
Bitset::Bitset(const string value) {
bitset = NULL;
assign(value);
}
Bitset::~Bitset() {
if (bitset != NULL) {
delete[] bitset;
}
}
int Bitset::size() {
return set_size;
}
void Bitset::operator= (const string value) {
assign(value);
}
bool Bitset::operator[] (const int index) const {
int offset;
if (index >= set_size) {
return false;
}
offset = (int) index/sizeof(unsigned char);
return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}
void Bitset::assign(const string value) {
int i, offset;
if (bitset != NULL) {
delete[] bitset;
}
bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];
for (i = 0; i < value.length(); i++) {
offset = (int) i/sizeof(unsigned char);
if (value[i] == '1') {
bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
} else {
bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
}
}
set_size = value.length();
}
My problem is my delete statements in both the deconstructor and assign method core dump. Is it not necessary to deallocate this memory? From what I've read so far it's always necessary to use the delete command whenever you call new.
EDIT: I've changed the code above to reflect one of the fixes. I added bitset = NULL in the constructor. This fixed the core dump in the assign method however I'm still getting errors in the deconstructor.

I think you should initialize bitset to NULL in your second constructor.
Why?
Because a pointer variable won't necessarily be initialized to NULL. So you may be trying to delete[] some random memory address when you use that second constructor.
So you should have:
Bitset::Bitset(const string value) : bitset(NULL)
{
assign(value);
}

Most likely you're copying a Bitset somewhere. You have not defined a copy constructor, not a copy assignment operator. The result of copying is then that you have two instances who both think they should deallocate the dynamically allocated array when they finish.
This is known as the Rule of Three: if you define any of destructor, copy constructor or copy assignment operator, then chances are that you'll need to define all three.
Now, about your code:
#include "bitset.h"
OK.
Bitset::Bitset() {
bitset = NULL;
}
(1) You didn't include a header that guaranteed defines NULL.
(2) you're not initializing the member set_size, so the check in the index operator may/will be using an indeterminate value, with Undefined Behavior.
(3) generally prefer to use initializer list rather than assignment (this avoids e.g. doing default construction followed by assignment).
Bitset::Bitset(const string value) {
bitset = NULL;
assign(value);
}
(4) Generally it's not a good idea to express construction in terms of assignment. Instead, express assignment in terms of construction.
Bitset::~Bitset() {
if (bitset != NULL) {
delete[] bitset;
}
}
(5) The check for NULL is unnecessary; you can safely delete a nullpointer.
int Bitset::size() {
return set_size;
}
(6) Uh, well, set_size was the member that wasn't initialized… Also, this member function should be const.
void Bitset::operator= (const string value) {
assign(value);
}
(7) An assignment operator should in general return a reference to the assigned-to object. That's just a convention, but it's what users of your class expect.
(8) Pass an in-argument by value or by reference to const. Generally, for built-in types choose by-value and for other types, such as std::string, choose reference to const. That is, the formal argument should better be string const& value.
bool Bitset::operator[] (const int index) const {
int offset;
if (index >= set_size) {
return false;
}
offset = (int) index/sizeof(unsigned char);
return (bitset[offset] >> (index - offset*sizeof(unsigned char))) & 1;
}
(9) First, again, the uninitialized set_size member.
(10) Then, note that sizeof(unsigned char) is 1 by definition. You probably want to use CHAR_BIT from <limits.h> here. Or just use 8 unless you plan on supporting Unisys computers (9-bit byte) or perhaps a Texas Instruments digital signal processor (16-bit byte).
void Bitset::assign(const string value) {
int i, offset;
if (bitset != NULL) {
delete[] bitset;
}
(11) The check for NULL is unnecessary.
bitset = new unsigned char[(int) ceil(value.length()/sizeof(unsigned char))];
(12) As already mentioned, sizeof(char) is 1 by definition.
(13) The division has integer arguments and so is an integer division, not a floating point division. Presumably what you want is the trick (a+b-1)/b?
for (i = 0; i < value.length(); i++) {
(14) Style: declare a variable as close to its first use as practically possible. Here it means declare the loop counter i directly in the loop head, like this: for( int i = 0, ....
offset = (int) i/sizeof(unsigned char);
(14) And ditto for offset. But for this variable you're not planning on changing its value, so also declare it const.
if (value[i] == '1') {
bitset[offset] |= (1 << (i - offset*sizeof(unsigned char)));
} else {
bitset[offset] &= ~(1 << (i - offset*sizeof(unsigned char)));
}
(15) Better rethink those shift operations!
}
set_size = value.length();
}
Cheers & hth.,

Make sure that the allocation size isn't zero, I suspect that's what's going on here, and that you're just writing to unallocated garbage memory. Running under valgrind will catch this too.

Related

Why my destructor shows that pointer being freed was not allocated c++

I want to implement 2 array addition, but when a destructor to the class SList
void operator+(SList list2) {
int totalLen = this->len + list2.len;
char** temp = new char* [totalLen];
for(int i = 0; i < len; i++) {
temp[i] = this->list[i];
}
for(int i = len, j = 0; i < totalLen; i++, j++) {
temp[i] = list2.get(j);
}
delete[] this->list;
this->list = temp;
this->len = totalLen;
cout << len << endl << endl;
}
Here are the get method that just return the dynamic array of char:
char* get(int i) {
if (i >= len) {
return "";
} else {
return list[i];
}
}
here are my class SList private variables:
private:
char** list;
int len;
char* generateString(){
char* str;
int n = rand() % 20 + 1;
str = new char[n + 1];
for(int i = 0; i < n; i++) {
str[i] = 'a' + rand()%26;
}
str[n] = '\0';
return str;
};
~SList() {
delete[] list;
}
It always shows malloc error on the destructor.
malloc: *** error for object 0x105007410: pointer being freed was not allocated
malloc: *** set a breakpoint in malloc_error_break to debug
Please help! I have carefully checked my delete method on the dynamic allocated array, but it always shows this error.
I have tried to check other delete from the other function, but none of them make the same malloc error. I have tried to commented the destructor method and everything work fine. But i really need to have destructor method here. I hope someone with more expertise on c++ can help me fix this malloc error and gave an explanation on which part i made a mistake.
Regardless what are other details of implementation, the destructor is not correct while you're using a data structure known as a "ragged array", i.e. list is a pointer to an array of pointers. delete[] would free the pointer array, but not char arrays pointed by its elements. You have to do something like this:
~SList() {
if(!list) return; // if we cannot guarantee that list isn't
// nullptr we have to check it,
// or result of list[i] would be undefined.
for(int i = 0; i < len; i++)
delete[] list[i];
delete[] list;
}
and you have to make sure that any of those pointers is either initialized by new expression or is equal nullptr.. It doesn't happen on its own. You have to make sure during construction and all operations. You didn't show any. Look for faults there.
The method get() is a disaster waiting to happen and is ill-formed, i.e. it doesn't follow C++ rules. The string literal "" returns const char*, always the same one and the statement return ""; is incorrect - some compilers only warn about it though. It cannot be deallocated by delete.
char* get(int i) {
if (i >= len) {
return nullptr; // "" - is not safe
} else {
return list[i];
}
}
Deleting a nullptr is a safe no-op. Deleting something that was't returned by new is a disaster.
The addition operator is taking list2 by value, which means that proper copy operations have to be implemented. You didn't show them either. Default implementation would just copy a pointer and destruction of local copy would deallocate memory used by original via ~SList() above. The operator have to return resulting object and should not modify one pointed by this. You had implemented an operator+=. The way you did it, it would work as
a+b; // a now contains result of concatenation.
It's simply weird to use. Proper operator would be
SList operator+(SList& list2);
In general, an object that deals with ownership of some resource, dynamic memory in our case, have to implement certain set of special member functions:
~SList();
SList(const SList& other);
SList(SList&& other); // move copy, source is a temporal.
SList& operator=(const SList& other);
SList& operator=(SList&& other); // move assignment
If that is done right, you can safely do the c = a + b; assignment.
Note that if you pass argument by reference you have to take in account that arguments of assigning operators aren't referencing the object pointed by this and act accordingly if they are. Otherwise you would destroy it and loose original data. On other hand copying argument is excessive and user-unfriendly due to increased cost and memory footprint. Concatenation of n-element and m-element array is expected to have memory footprint of n+m elements , not n+2*m.

Overloading + operator to concatenate two strings in C++ (Some doubts)

I have just started learning C++ a few days back. I was given an assignment to demonstrate + operator overloading to concatenate two strings. I came up with this solution:
#include <iostream>
using namespace std;
class Strcpy{
private:
char* wrd;
int len;
public:
Strcpy();
Strcpy(char* );
void Display();
friend Strcpy operator + (Strcpy, Strcpy);
friend Strcpy concatinator(Strcpy, Strcpy);
};
Strcpy :: Strcpy(){
wrd = '\0';
len = 0;
}
Strcpy :: Strcpy(char* w){
int i; len = 0;
for(i = 0; w[i] != '\0' ; i++)
len ++;
wrd = w;
}
void Strcpy :: Display(){
cout << "\nOutput: " << wrd << " "<< len;
}
Strcpy operator + (Strcpy obj1, Strcpy obj2){
Strcpy temp;
int i;
temp.wrd = new char[obj1.len + obj2.len];
temp = concatinator(temp, obj1);
temp = concatinator(temp, obj2);
temp.wrd[temp.len] = '\0';
return temp;
}
Strcpy concatinator(Strcpy obj, Strcpy temp){
for(int i = 0; temp.wrd[i] != '\0'; i++)
{
obj.wrd[obj.len] = temp.wrd[i];
obj.len++;
}
return obj;
}
int main(){
Strcpy word, word_I("Hello"), word_II("World");
word = word_I + word_II;
word.Display();
return 1;
}
Some things to be noted:
deprecated conversion from string constant to 'char*' [-Wwrite-strings] I realize this is being caused because I am converting an immutable type to a mutable one but what alternative approach can I try to get rid of this.
I want to avoid using friend functions, but the overloaded operator needs two arguments which isn't possible if it remains a class member.
The following line works the same even if it is changed, why is this happening:
temp.wrd = new char[obj1.len + obj2.len];
//changed to
temp.wrd = new char[//any number here];
I want avoid using string functions if that is possible at all.
Whenever i try taking an input in the following form, it crashes:
char* Strcpy :: get(){
char* temp;
cin >> temp;
return temp;
}
int main(){
Strcpy word;
Strcpy word_I(word.get()), word_II(word.get());
word = word_I + word_II;
word.Display();
return 1;
}
Lastly, I would appreciate any help that would help me improve on the existing solution and some explanation so as to why it is better and the mistakes I am making.
deprecated conversion from string constant to 'char*' [-Wwrite-strings] I realize this is being caused because I am converting an immutable type to a mutable one but what alternative approach can I try to get rid of this.
You never modify *w, so you can use a pointer to const instead.
I want to avoid using friend functions, but the overloaded operator needs two arguments which isn't possible if it remains a class member.
The first argument of a member operator overload is the implicit this pointer. If you declare Strcpy Strcpy::operator+(const Strcpy&) const, it will be a binary operator. That said, the friend operator is probably a better approach.
The following line works the same even if it is changed, why is this happening:
temp.wrd = new char[obj1.len + obj2.len];
//changed to
temp.wrd = new char[//any number here];
It will work as long as "any number" is large enough to contain the entire string. If you write outside of the bounds, the behaviour is undefined.
Whenever i try taking an input in the following form, it crashes:
char* temp;
cin >> temp;
The stream extraction operator requires that a char* passed to it must point to an array sufficiently large to contain the user input. You forgot to initialize temp, so the requirement is not satisfied. As a result, the behaviour of the program is undefined. Solution: Allocate some memory and initialize temp to point to that memory.
The same bug occurs the constructor Strcpy(char*). You don't initialize this->wrd, but you dereference it. Therefore the behaviour is undefined. The solution is the same as above.
If I understood this right
I want to avoid using friend functions, but the overloaded operator
needs two arguments which isn't possible if it remains a class member.
your statement is wrong.
Sample for a binary + operator in a class:
#include <iostream>
class Int {
private: int _i;
public:
Int(int i = 0): _i(i) { }
Int operator + (const Int &i) const
{
return Int(_i + i._i);
}
int get() const { return _i; }
};
int main(int, char**)
{
Int i1(1), i2(2);
Int i;
i = i1 + i2;
std::cout << "i: " << i.get() << std::endl;
return 0;
}
Compiled and tested with gcc on cygwin:
$ g++ -o test-op-plus test-op-plus.cc
$ ./test-op-plus.exe
i: 3

Custom implementation of a bool vector with bit representation - how to implement operator[]

Disclaimer - this is a school assignment, however the problem is still interesting I hope!
I have implemented a custom class called Vector<bool>, which stores the bool entries as bits in an array of numbers.
Everything has gone fine except for implementing this:
bool& operator[](std::size_t index) {
validate_bounds(index);
???
}
The const implementation is quite straight forward, just reading out the value. Here however I can't really understand what to do, and the course is a specialization course on C++ so I'm guessing I should do some type-deffing or something. The data is represented by an array of type unsigned int and should be dynamic (e.g. push_back(bool value) should be implemented).
I solved this implementing a proxy class:
class BoolVectorProxy {
public:
explicit BoolVectorProxy(unsigned int& reference, unsigned char index) {
this->reference = &reference;
this->index = index;
}
void operator=(const bool v) {
if (v) *reference |= 1 << index;
else *reference &= ~(1 << index);
}
operator bool() const {
return (*reference >> index) & 1;
}
private:
unsigned int* reference;
unsigned char index;
};
And inside the main class:
BoolVectorProxy operator[](std::size_t index) {
validate_bound(index);
return BoolVectorProxy(array[index / BLOCK_CAPACITY], index % BLOCK_CAPACITY);
}
I also use Catch as a testing library, the code passes this test:
TEST_CASE("access and assignment with brackets", "[Vector]") {
Vector<bool> a(10);
a[0] = true;
a[0] = false;
REQUIRE(!a[0]);
a[1] = true;
REQUIRE(a[1]);
const Vector<bool> &b = a;
REQUIRE(!b[0]);
REQUIRE(b[1]);
a[0] = true;
REQUIRE(a[0]);
REQUIRE(b[0]);
REQUIRE(b.size() == 10);
REQUIRE_THROWS(a[-1]);
REQUIRE_THROWS(a[10]);
REQUIRE_THROWS(b[-1]);
REQUIRE_THROWS(b[10]);
}
If anyone finds any issues or improvements that can be made, please comment, thanks!
Basically implementing operator[] is the same as implementing const operator[] as you might expect, it's just that one is writable (lvalue) and the other is read only (rvalue).
I think you've got a understanding of the problem : you can convert an unsigned int into a bool using bitwise operations, and you can also say "if the nth bool is modified in X, do a bitwise operation with X and it's done !". But this operator means : I want a lvalue of the bool so I can modify it whenever I want and have an impact on the integer associated. It means that you want a reference of a bool, or in your case a reference of a single bit, so you can modify that bit on the fly. Unfortunately you can't reference a single bit, the smallest you can do is a whole byte (with char), so you would have to take a chunk of at least 7 other booleans with you. That's not what you want.
That being said, I understand that it might be for your assignment, but converting bools into multiple unsigned int is more like useless C optimization to me. You would be better with having a single array of bools (C-style), and doing the memory handling manually, because that is almost what you are doing. Plus with that method, you would actually be able to reference one single boolean (and be able to modify it) without touching the others. Is it mandatory that you have to use an array of unsigned int for this assignment ?

How to dereference a n-levels void pointer to an int pointer

I'm trying to implement the following function:
int foo(const void *p, unsigned int n);
Where p is actually a n-levels pointer to an int value and the function must return that value. So:
n = 0: value = (int)(p);
n = 1: value = *(int*)(p);
n = 2: p is a pointer to a pointer to an int value
And so on...
So, I think that the following implementation may be correct:
int foo(const void *p, unsigned int n) {
if (!n) {
return (int)p;
}
return foo((void*)*((int*)p), n - 1);
}
But, in this code, I assume that size of a pointer always equals a size of an int, and I know it is not true. However, since p is always a pointer to pointer to int (n times), I think that maybe I can always cast p to pointer to int as I do in the code.
Is my idea correct? I cannot found any problem similar to this on internet.
Thanks in advance!
Your bottom case of the recursion is not correct, since this supposes that void* and int have the same width.
if (n == 1) return *(int*)p;
Would be better.
this assumes that your int is no bigger than a void*:
int foo(const void *p, unsigned int n) {
if (!n) {
return reinterpret_cast<int>(p);
}
return foo(*static_cast<void**>(p), n - 1);
}
we can avoid that assumption for everything except the n=0 case:
int foo(const void *p, unsigned int n) {
if (!n) {
return reinterpret_cast<int>(p);
}
if (n==1) {
return *static_cast<int*>(p);
}
return foo(*static_cast<void**>(p), n - 1);
}
In C you can replace the static_cast<X> and reinterpret_cast<X> clauses with (X).
I'm not sure what you are trying to accomplish, but I suspect there is a better approach.
Anyway, a pointer to something is the same size as a pointer to a pointer to something, etc.
So you can cast a (void*) to a (void**).
But casting a pointer to an int may loose information, because sizeof(void*) may be > sizeof(int).
You should write:
int foo(const void *p, unsigned int n) {
//if n is 0, then p is already an int, but has been casted to a void*
//This should probably never happend, so you should assert that n > 0
//if n is 1, then p is actually a pointer to an int
if (n == 1) return *(int*)p;
//else dereference it (by casting it to a (void**) and *then* dereferencing it)
return foo(*(void**)p, n-1);
}
In general it's usually better to stick with iterative solution, rather than recursive, if it's possible.
int foo(void *p, unsigned int n) {
for (unsigned int i = 0; i < n; ++i) {
p = *((void**)p);
}
return (int)p;
}
IDEONE: demo
It lets you avoid problems with theoretiaclly possible stack overflow for large ns (I have no idea why would you need to dereference 1000+ levels deep pointer, but I have no idea why you need this function in the first place, so let's keep the function safe) and avoids unnecessary function call overhead (yes, it might get optimized by the compiler, but why not write it optimally in the first place?).

new operator overloading in c++ example

I have the following code which I can't understand the status after one line in main.
#include <iostream>
typedef unsigned long size_t;
const int MAX_BUFFER=3;
int buf[MAX_BUFFER]={0}; //Initialize to 0
int location=0;
struct Scalar {
int val;
Scalar(int v) : val(v) { };
void* operator new(size_t /*not used*/) {
if (location == MAX_BUFFER) {
throw std::bad_alloc();
} else {
int* ptr = &buf[location];
if ( buf[location] == 0) {
location++;
} else {
return ptr;
}
}
}
void operator delete(void* ptr) {
size_t my_loc = (int*)ptr - buf;
buf[my_loc] = location;
location = my_loc;
}
};
int main() {
Scalar *s1 = new Scalar(11);
cout << buf[0];
}
Why does the array buf in the end of this code contains the value 11 at the...?
I'm am not sure where the val input plays a role.
I don't understand why you only conditionally increment location after an allocation, and if you increment location, then the function doesn't execute a return statement which is undefined behavior.
Your deallocation strategy is completely broken unless objects are only deallocated in the exact opposite order of allocations. Additionally, after the array element has been used for one allocation, it won't ever be used again due to the assignment in the deallocator.
As for the actual question: the first Scalar allocated is allocated at the same location as the buffer, so the first Scalar and buf[0] share the same memory. As they're both composed of a single int, writes to one might be readable from the other. And when you construct the Scalar, it assigns the value 11 to the shared memory. I think doing this is undefined behavior, but I'm not certain.
The value 11 gets into the buffer thanks to
Scalar(int v) : val(v) { };
that takes the parameter and copies it into the member val.
If the class instance is allocated at the address of the buffer (because of the customized operator::new (size_t) implementation) then it's possible that its first member ends up in the first array element.
Note that this code is totally broken for several reasons already pointed out by Mooing Duck.