I am attempting to dynamically allocate memory to the heap and then delete the allocated memory. Below is the code that is giving me a hard time:
// String.cpp
#include "String.h"
String::String() {}
String::String(char* source)
{
this->Size = this->GetSize(source);
this->CharArray = new char[this->Size + 1];
int i = 0;
for (; i < this->Size; i++) this->CharArray[i] = source[i];
this->CharArray[i] = '\0';
}
int String::GetSize(const char * source)
{
int i = 0;
for (; source[i] != '\0'; i++);
return i;
}
String::~String()
{
delete[] this->CharArray;
}
Here is the error I get when the compiler tries to delete the CharArray:
0xC0000005: Access violation reading location 0xccccccc0.
And here is the last call on the stack:
msvcr100d.dll!operator delete(void * pUserData) Line 52 + 0x3 bytes C++
I am fairly certain the error exists within this piece of code but will provide you with any other information needed. Oh yeah, using VS 2010 for XP.
Edit: Heres my String.h
// String.h - string class
#pragma once
#define NOT_FOUND -1
class String
{
public:
String();
String(char* source);
static int GetSize(const char * source);
int Find(const char* aChar, int startPosition = 0);
~String();
private:
char* CharArray;
int Size;
};
Change your default ctor; given the error you're getting, the delete call is trying to delete a pointer that has never been initialized.
String::String() : Size(0), CharArray(NULL) {}
Also, beware of the "copy constructor". You might want to make it private just to be sure you're not triggering it implicitly. (It doesn't need to be implemented if you don't intend to call it, just stick the function prototype into your class definition.) Might as well similarly "disable" the assignment operator.
class String
{
// other stuff
private:
String(String&);
String& operator=(String&);
};
This addition fulfills the "Rule of Three," which says that if any class needs a destructor, a copy constructor, or an assignment operator, it probably needs all three.
Edit: see http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29
String::String(): CharArray( 0 ) {}
You're not initializing CharArray in every constructor, so in some cases you're deleting an uninitialized pointer.
You have multiple constructors, but only 1 of them calls new. Your destructor always calls delete so there is your error.
I think #dash-tom-bang is correct. You're probably copying String and then deleting its data twice. I'll keep my old answers here for reference, though.
You're going to need to post the code that uses String, but I can notice a few problems here:
What if source is NULL in the constructor? Immediately you have a Null Pointer Exception. What's worse, if you get this exception, the destructor will attempt to delete memory that was never allocated. This could cause the error described above if you're using try...catch.
GetSize should not be a member function of String because it doesn't use any member variables. At the very least it should be static.
Related
I Have a doubt in the following code, there is a destructor delete line[] inside the destructor, I just want to know if there any stack over flow for this delete which can be a result of recursive call to destructor.
class Line {
public:
char *line;
Line(const char *s = 0) {
if (s) {
line = new char[strlen(s)+1];
strcpy(line, s);
} else {
line = 0;
}
}
~Line() {
delete[] line; //----------> how this delete will work?
line = 0;
}
Line &operator=(const Line &other) {
std::cout <<"go"<< endl;
delete[] line; //----------> purpose of using this delete??
line = new char[other.len()+1];
strcpy(line, other.line);
return *this;
}
int operator<=(const Line &other) {
int cmp = strcmp(line, other.line);
return cmp <= 0;
}
int len() const {
return strlen(line);
}
};
int main() {
Line array[] = {Line("abc"), Line("def"),
Line("xyz")};
Line tmp;
}
The delete inside the overloaded assignment operator is to clean the memory before assigning new memory(I have read it somewhere, correct me if I am wrong), but does this delete will call the destructor?
Please Explain
No, it will not.
This delete statement will delete the char array. The destructor of Line is only called when destroying the Line object. That is however not the case here.
The variable line and the object/class Line are different things.
The line variable is a member-variable in the Line class. So those two names seem the same but are completly different.
delete[] line; pairs the new char[strlen(s)+1]; statements in the constructor and assignment operator. Note that delete[] line; is a no-op if line is set to nullptr, which is what the else branch assignment does, although it sloppily uses 0 in place of nullptr.
Be assured the destructor is not called recursively. It's just that the destructor is used to release any allocated memory.
But using std::string line; as the class member variable, or perhaps even the entire class itself would be far, far easier. There are some subtle bugs in your code - self assignment being one of them, and the copy constructor is missing. Let the C++ Standard Library take care of all this for you. In short you could write
int main() {
std::string array[] = {"abc", "def", "xyz"};
std::string tmp;
}
The argument to delete[] is a char*, ie there is no destructor called (and also there is no recursive calling of the destructor).
If you had a destructor like this:
~Line() { delete this; } // DONT DO THIS !!! (also for other reasons it is not OK at all)
this would attempt to call itself recursively, but your code looks fine.
In the assignment operator
line = new char[other.len()+1];
will allocate new memory and assign a pointer (pointing to this memory) to line. This will cause that you have no handle to the old memory anymore and to avoid a leak you need to delete it before.
C++ by default takes care of delete[] for char*, therefore you do not need to do anything.
Following my understanding of C++ convention, I have:
class BlockRepresentation : public FPRepresentation
{
private:
class Block
{
public:
int id;
int fpDimensions;
int* position; // pointers in question
int* blockDimensions; // pointers in question
~Block();
};
std::vector<Block> all_blocks;
public:
BlockRepresentation( int count, int dimensions, int volumn[] );
void AddBlock( int id, int position[], int dimensions[] );
std::string ToGPL();
};
where new blocks are created in AddBlock:
void BlockRepresentation::AddBlock( int id, int position[],
int dimensions[] )
{
Block newBlock;
newBlock.id = id;
newBlock.fpDimensions = fpDimensions;
newBlock.position = new int[fpDimensions]; // pointers in question
newBlock.blockDimensions = new int[fpDimensions]; // pointers in question
for (int i = 0; i < fpDimensions; ++i)
{
newBlock.position[i] = position[i];
newBlock.blockDimensions[i] = dimensions[i];
}
all_blocks.push_back( newBlock );
}
so I have the following destructor:
BlockRepresentation::Block::~Block()
{
delete[] position;
delete[] blockDimensions;
}
but then I get:
rep_tests(11039,0x7fff71390000) malloc: *** error for object 0x7fe4fad00240: pointer being freed was not allocated
Why should I not delete[] the 2 pointers here?
As was pointed out in the comments, you violated the rule of three, and the violation is very obvious:
{
Block newBlock;
// snip
all_blocks.push_back( newBlock );
}
When this function returns, the newBlock object goes out of scope, and its destructor will delete all the newed arrays.
But you push_back()ed this object. This constructs a copy of the object into the vector. Because your Block does not define a copy constructor, the default copy-constructor simply makes a copy of all the pointers to the newed arrays.
If you somehow manage to avoid dereferencing the no-longer valid pointers, or you survived that experience, you're not of the woods yet. That's because, when the vector gets destroyed, and its Blocks get destroyed, their destructors will, once again, attempt to delete the same newed arrays that were already deleted once before.
Instant crash.
There is nothing wrong with your Block destructor. It is doing its job, which is releasing the memory that is pointed to by your two int * member variables. The problem is that the destructor is being called on the same pointer value multiple times, which results in a double-free error.
The entity that causes this is the std::vector<Block>, since a std::vector will make copies of your Block object, and your Block object is not safely copyable.
Since the member variables of Block that are pointers are position and blockDimensions, the most painless way to alleviate this issue is to use std::vector<int> instead of int *, as demonstrated by this sample program.
However, if you really wanted to use int *, you would need to implement a user-defined copy constructor. In addition, a user-defined assignment operator would complement the copy constructor. This is what is called the Rule of Three.
#include <algorithm>
//...
class Block
{
public:
int id;
int fpDimensions;
int *position;
int *blockDimensions;
Block() : position(nullptr), blockDimensions(nullptr),
id(0), fpDimensions(0) {}
~Block()
{
delete [] position;
delete [] blockDimensions;
}
Block(const Block& rhs) : id(rhs.id), fpDimensions(rhs.fpDimensions),
position(new int[rhs.fpDimensions]),
blockDimensions(new int[rhs.fpDimensions])
{
std::copy(rhs.position, rhs.position + fpDimensions, position);
std::copy(rhs.blockDimensions, rhs.blockDimensions + fpDimensions,
blockDimensions);
}
Block& operator=(const Block& rhs)
{
Block temp(rhs);
std::swap(temp.position, position);
std::swap(temp.blockDimensions, blockDimensions);
std::swap(temp.id, id);
std::swap(temp.fpDimensions, fpDimensions);
return *this;
}
};
See the live sample here.
See all of the hoops we had to jump through to get the Block class to behave correctly when used within a std::vector, as opposed to simply using std::vector<int>?
For future visitors
It turns out I didn't have a copy assignment operator defined in my custom class, and therefore the compiler defaulted to "copy the object's pointer" behavior.
If you're confused about what a copy assignment operator is, just like I was, this resource may help you figure out what a "copy assignment operator" looks like in C++.
The original problem prompt is below. (Links to the original source code will expire in a month; sorry!)
I'm working on a console application which simulates a bookstore, but keep on getting a _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) error message in my program during execution. After doing some searching around (and some frustrating debugging), I've come to the conclusion that my object's destructor is getting called twice. I hope the code snippets below will make it a little clearer what I mean. (Clicking on the file names will open a pastie with the relevant code for easier reading/decluttering.)
bookdata.h
#ifndef BOOKDATA_H
#define BOOKDATA_H
class bookData {
private:
char* bookTitle;
char* isbn;
char* author;
char* publisher;
char* dateAdded;
int qtyOnHand;
double wholesale;
double retail;
public:
bookData();
bookData(char* title, char* isbn, char* author, char* publisher, char* date, int qty, double wholesale, double retail);
bookData(bookData& book); // Meant to be called during memberwise assignment
~bookData();
// Various setter & getter funcs
};
#endif
bookData.cpp
#include "globals.h"
#include "bookData.h"
using namespace std;
// Variables in caps are const ints defined in globals.h
bookData::bookData() {
bookTitle = new char[TITLE_LENGTH];
isbn = new char[ISBN_LENGTH];
author = new char[AUTHOR_LENGTH];
publisher = new char[PUBLISHER_LENGTH];
dateAdded = new char[DATE_LENGTH];
qtyOnHand = 0;
wholesale = 0;
retail = 0;
char emptyTitle[2];
emptyTitle[0] = '\0';
setTitle(emptyTitle);
}
// Other constructors are overloaded version of bookData & copy data;
// See example setter function below destructor
bookData::~bookData() {
if (bookTitle)
delete [] bookTitle;
else
return;
delete [] isbn;
delete [] author;
delete [] publisher;
delete [] dateAdded;
}
// Setter functions are of this form (excl. ints & doubles)
void bookData::setTitle(const char* input) {
for (int len = 0; len < TITLE_LENGTH - 1; len++) {
*(bookTitle + len) = *(input + len);
if (*(input + len) == '\0')
break;
else if (len == TITLE_LENGTH - 2)
*(bookTitle + ++len) = '\0';
}
}
// Getter functions are of this form (excl. ints & doubles)
const char* bookData::getTitle() { return bookTitle; }
reports.cpp (the file that's calling the destructor twice)
void repQty() {
// Again, variables in all caps are defined in globals.h if you don't see
// their declaration
bookData bookArray[MAX_RECORDS];
// Global function which populates bookArray from a datafile
bookData* books = getBooks(bookArray);
// Some code to find the memory address of the first and last book in the records
bookData* HEAD = books;
// Keep advancing until books no longer points to a non-empty bookData object
// "Empty" defined as book's bookTitle variable starting with '\0'
bookData* TAIL = --books;
// Need all 3 pointers for a naive, in place insertion/linear sort routine
// Outputs book data following the sort
// Before returning, calls the destructors for the books in bookArray
// Also calls the destructor for books, HEAD, and TAIL as well
// ...which were already called as part of the bookArray's destructor calls
// Which is where I have my problem now
}
Bonus: globals.h
As you may have noticed, I've already attempted to check whether the bookData object has already been deleted by using if (bookTitle) in the destructor function, but it still evaluates as true when I'm running it through VS's Step Into functionality. Short of nuking the destructor all together, what can I do to get around this problem and make the destructor prematurely exit if the object in question has already been deallocated?
I've already attempted to check whether the bookData object has already been deleted by using if (bookTitle) in the destructor function
Since delete[] doesn't set the pointer to NULL, the check is effectively a no-op.
Even if you set the pointer to NULL manually, you'd be tackling the symptoms of the problem rather than the root cause.
The root cause is that you're not implementing the copy assignment operator, thereby violating the rule of three. What happens is that you're using the implicitly-generated copy assignment operator:
swap = *books;
*books = *(books - 1);
*(books - 1) = swap;
and that operator doesn't do the right thing: it copies the pointers instead of copying the data. The double deletes are a direct consequence of that.
Additionally, the implementation of the copy constructor could be buggy, but it's hard to be sure without seeing its source code.
P.S. You'd do yourself a massive favour by using std::string instead of C strings. Also, std::vector is to be preferred to C arrays.
I tried to search same questions, but not one helped me. When I run program I get the "A Buffer Overrun has occurred..." error.
Constr:
Player(char* n)
{
length = strlen(n);
name = new char[length+1];
for(unsigned int i(0); i < length; i++)
name[i] = n[i];
name[length] = '\0';
}
Destr:
~Player(void)
{
delete [] name;
}
I've NULL terminated string and don't get out of bounds, what is problem?
There's no obvious error in the code you've posted, but trying to manage dynamic memory by juggling raw pointers will almost inevitably lead to errors like this.
Perhaps you haven't correctly implemented or deleted the copy constructor and copy-assignment operator, per the Rule of Three. In that case, copying a Player object will give two objects with pointers to the same array; both of them will try to delete that array, giving undefined behaviour.
The simplest solution is to manage your string with a class designed for managing strings. Change the type of name to std::string, and then the constructor can simply be something like
explicit Player(std::string const & n) : name(n) {}
and there's no need to declare a destructor (or move/copy constructor/assignment operators) at all.
So... a solution by using an std::string has been provided, but let me give another solution, keeping your member variables intact.
The problem is this. Suppose you have this code somewhere:
Player p1("Bob"); // Okay
Player p2("Annie"); // Okay
p2 = p1; // Oops! (1)
Player p3(p1); // Oops! (2)
At (1), the method Player& Player::operator=(const Player&) is called. Since you didn't provide one, the compiler generates one for you. When it does, it simply assumes that it may copy over all member variables. In this case, it copies over Player::name and Player::length. So, we have p1.name == p2.name. Now when the destructor of p2 is called, the allocated memory pointed to by p2.name is deleted. Then when the destructor of p1 is called, the same memory will be deleted (since p1.name == p2.name)! That's illegal.
To fix this, you can write an assignment operator yourself.
Player& Player::operator = (const Player& other)
{
// Are we the same object?
if (this == &other) return *this;
// Delete the memory. So call the destructor.
this->~Player();
// Make room for the new name.
length = other.length;
name = new char[length + 1];
// Copy it over.
for (unsigned int i = 0; i < length; ++i) name[i] = other.name[i];
name[length] = '\0';
// All done!
return *this;
}
At (2), the same problem occurs. You do not have a copy constructor, so the compiler generates one for you. It will also assume that it may copy over all the member variables, so when the destructors get called, they'll try to delete the same memory again. To fix this, also write a copy constructor:
Player::Player(const Player& other)
{
if (this == &other) return;
length = other.length;
name = new char[length + 1];
for (unsigned int i = 0; i < length; ++i) name[i] = other.name[i];
}
At the end of the day you should use an std::string though.
At my university, there is a practical programming test in C++ - and I'm stuck with an example where I am unsure about wheter or not the task in question is even valid and possible to complete correctly.
The (simple) tasks:
Complete the destructor of Person, so that the allocated name is freed again
In the main function, replace //??? with the statement required to free the previously allocated memory
At first, the tasks seemed trivial for me: For the destructor, simply write delete[] name and in the main function, use delete[] friends. Presumably, that is also what the author of this example meant us to do.
However:
There seems to be a flaw in this code example, which causes memory leaks as well as destructors to be called more than once.
The person class has no assignment operator =, meaning that as the existing Person objects such as maria are assigned to slots in the friends array in the main function, the internal allocated names are not copied. So two objects now share the same internal char* pointer! Moreover, the pointer to the name of the Person previously residing in the said array slot is permanentely lost, leading to an unavoidable memory leak.
As delete[] friends; is called - the objects in the array are destroyed - leading to their destructors being called and freeing their name members. When the program ends, though, the local Person objects in the scope of main are destructed - which of course have their name members still pointing to memory which was already freed before.
The actual question:
Is this test example flawed, or am I missing something?
Can the issues listed above be fixed if sticking fully to carrying out the given tasks (altering just the implementation of the destructor, and inserting new code at the commented part in the main function)?
..
#include <iostream>
using namespace std;
int strlen(const char *str) {
if (str==0) return 0;
int i=0;
for (; str[i]; ++i);
return i;
}
void strcpy(const char *src, char *dest) {
if (src==0 || dest==0) return;
int i=0;
for (; src[i]; ++i) dest[i]=src[i];
dest[i]=’\0’;
}
class Person {
char *name;
public:
Person(const char *str = "Susi") {
name = new char[strlen(str)+1];
strcpy(str,name);
}
Person(const Person &p) {
name = new char[strlen(p.name)+1];
strcpy(p.name,name);
}
~Person() {
//...
}
void change() {
name[4]='e';
}
ostream &print(ostream &o) const {
o<<name;
return o;
}
};
int main() {
Person maria("Maria"), peter("Peter"), franz("Franz"), luisa("Luisa");
Person mary(maria);
Person luise;
Person p(luise);
Person *friends= new Person[7];
friends[0]=maria;
friends[1]=peter;
friends[2]=franz;
friends[3]=luisa;
friends[4]=mary;
friends[5]=luise;
friends[6]=p;
friends[5]=luisa;
friends[3].change();
friends[4].change();
for (int i=0; i<7; ++i) {
friends[i].print(cout);
cout<<endl;
}
//???
return 0;
}
You are absolutely right. You can fix it by only making changes at the indicated positions, however they are going to be rather extreme:
Replace the //... inside the destructor with:
delete[] name;
}
Person& operator=(const Person& other)
{
if (this != &other) {
delete[] name; // not completely exception-safe!
name = new char[strlen(other.name)+1];
strcpy(other.name,name);
}
return *this;
Another serious problem is redefining a standard function (strcpy) with a new definition that reorders the arguments.
(See also: SQL injection attacks, which also cause existing pairs of syntax elements, frequently quotes and parentheses, to be re-paired with inserted syntax elements)
Yes, the test example is flawed, possibly it was done consciously. Class Person definitely need assignment operator, remember the Rule Of Three.
No, it's not possible. Default compiler-generated assignment operator will leak memory allocated by objects in friends array and double-delete memory allocated by auto Person objects.
For every new there should be a delete[].