C++ delete[] crash - c++

Program crashes when I'm trying to delete[] an array that was allocated with new[]. I don't see any reasons why this shouldn't work. The array is allocated in method and deleted in the end of it, it's local, everything should be fine, but it's not.
I don't see any exception name that was thrown in debug, that's why I don't know where to dig.
Through debug I see that crash is happening at first delete[] operator.
Without those two deletes no crashes happening, but I don't want something to float in memory.
void Atbash::EncryptString(string t)
{
char *cOriginalString;
char *cEncryptedString;
unsigned int originalStringLength;
unsigned int i;
unsigned short j = 0;
originalString = t;
originalStringLength = originalString.length();
cOriginalString = new char(originalStringLength + 1);
cEncryptedString = new char(originalStringLength + 1);
strcpy_s(cOriginalString, originalStringLength + 1, originalString.c_str());
cOriginalString[originalStringLength] = '\0';
for (i = 0; i < originalStringLength; i++)
{
while (cOriginalString[i] != alphabet[j])
{
j++;
}
cEncryptedString[i] = alphabet[N - j - 2];
j = 0;
}
cEncryptedString[originalStringLength] = '\0';
encryptedString = cEncryptedString;
delete[] cOriginalString;
delete[] cEncryptedString;
}
originalString and encryptedString are of "string" type.

You aren't allocating a char[], just a plain old char. Note that you should be using square braces ([]) and not parenthethis (()):
cOriginalString = new char[originalStringLength + 1];
// Here ------------------^------------------------^
cEncryptedString = new char[originalStringLength + 1];
// And here ---------------^------------------------^

You can process individual characters in a std::string and it will both simplify your code and make it more robust. Here is one possible implementation.
void Atbash::EncryptString(string originalString)
{
encryptedString.clear();
encryptedString.reserve(originalString.size());
for (auto ch:originalString)
{
auto index= alphabet.find(ch);
if (index != npos)
encryptedString += alphabet[N - index - 2];
}
}

Related

C++ char class function append

void CMPT135_String::append(const CMPT135_String &s) /*12*/
{
char *temp = new char[this->getLength()+1];
int len = CMPT135_String::cstrlen(buffer);
for (int i =0; i < len; i++)
temp[i] = this->operator[](i);
for (int i = 0; i < s.getLength()+1; i++)
temp[len+i] = s[i];
if(this->getLength() >0)
delete[] this->buffer;
this->buffer = temp;
}
I have been working with this append() member function for a custom string class.
The function works fine, but after it runs I get a popup window showing up:
Windows has triggered a breakpoint in CMPT135_Assignment1.exe.
This may be due to a corruption of the heap, which indicates a bug in Assignment1.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while CMPT135_Assignment1.exe has focus.
The output window may have more diagnostic information.
Please tell me what is going wrong with this.
You are not allocating enough memory for the new buffer. You are only allocating enough memory to copy this->getLength() number of characters from this, there is no room to also copy s.getLength() number of characters from s into that new buffer, so your second loop is corrupting random memory past the end of the new buffer.
Try something more like this instead:
void CMPT135_String::append(const CMPT135_String &s) /*12*/
{
int this_len = this->getLength();
int s_len = s.getLength();
int new_len = this_len + s_len;
char *temp = new char[new_len + 1];
for (int i = 0; i < this_len; ++i)
temp[i] = this->operator[](i);
for (int i = 0; i < s_len; i++)
temp[this_len + i] = s[i];
temp[new_len] = '\0';
delete[] this->buffer;
this->buffer = temp;
}

C++. How can I free memory correctly?

Written code to find and remove the largest word in a string without the using of library functions. Everything works fine. But when I want to free memory, the result is negative (displays an empty line). If you remove the call to the memory release function, everything will work correctly, but there will be a leak of memory.
How do I fix it? Please help me.
#include <iostream>
using namespace std;
int length(char *text) // string length
{
char *begin = text;
while(*text++);
return text - begin - 1;
}
int size(char **text) // size of two-dimensional array
{
int i = 0;
while(text[i]) i++;
return i;
}
void free_memory(char **text)
{
for(int i=0; i<size(text); i++)
delete text[i];
delete [] text;
}
char **split(char *text, char delim)
{
int words = 1;
int len = length(text);
for(int i=0; i<len; i++)
if(text[i] == delim) words++;
char **result = new char*[words + 1];
int j = 0, t = 0;
for(int i=0; i<words; i++)
{
result[i] = new char[len];
while(text[j] != delim && text[j] != '\0') result[i][t++] = text[j++];
j++;
t = 0;
}
result[words + 1] = nullptr;
return result;
}
char *strcat(char *source, char *destination)
{
char *begin = destination;
while(*destination) destination++;
*destination++ = ' ';
while(*source) *destination++ = *source++;
return begin;
}
char *removeWord(char *in_string)
{
char **words = split(in_string, ' ');
int max = length(words[0]);
int j = 0;
for(int i=0; i<size(words); i++)
if(max < length(words[i]))
{
max = length(words[i]);
j = i;
}
int index;
char *result;
if(!j) index = 1;
else index = 0;
result = words[index];
for(int i=0; i<size(words); i++)
if(i != j && i != index)
result = strcat(words[i], result);
free_memory(words); // I want free memory here
return result;
}
int main()
{
char text[] = "audi and volkswagen are the best car";
cout << removeWord(text) << endl;
return 0;
}
In fact, this is C style programming - not C++. I see that your aim is to implement everything from scratch, possibly for practicing. But even then, your code is not designed/structured properly.
Besides that, you also have several bugs in your code:
result[words + 1] = nullptr; must be result[words] = nullptr;
You need result[i][t] = '\0'; after the while loop in split
delete text[i] must be delete [] text[i]
You cannot assign to your result pointer memory from words, then free it and then return it for use by the caller.
There is at least one further bug in the second half of removeWord. It would be tedious to try to understand what you are trying to do there.
You might want to start with a simpler task. You also should proceed step-by-step and check each function for correctness independently first and not implement everything and then test. Also take a look at the tool valgrind for memory checking - if you use Linux.
The way you free memory correctly is to use RAII:
Only use new and new[] in constructors
Pair those with delete and delete[] in the corresponding destructor
Use automatic storage duration objects as much as possible
If you are specifically not using std::string and std::vector etc, for reasons of learning pointers, you will end up writing some small number of classes that resemble string and vector and unique_ptr, and then you go about programming as if you were using the std versions.
You have two issues. First is that result is assigned to a memory location in words. Second, is that you're storing the result of strcat in words[i] which will likely not have enough room (see strcat documentation).
result = new char[len(in_string)+1]; // +1 for space for null char
// the old loop reversed the word order -- if you want to keep doing
// that, make this a descending loop
for(int i=0; i<size(words); i++)
if(i != j && i != index)
strcat(result, words[i]);
free_memory(words);
return result;
So that when you free words, what result points to is also free'd. You would then need to free your result in main().
int main()
{
char text[] = "audi and volkswagen are the best car";
char * result = removeWord(text);
cout << result << endl;
delete[] result;
return 0;
}

Program not exiting because of delete[]

So my program executes as expected and prints out the correct result. The only issue is that after it is done it does not exit. If I wait a few more seconds windows pops up an error message saying "bignumbs.exe has stopped working". Here is the code to the new function which seems to be causing the problem.
void BigInt::u_basic_mult(const BigInt& n, int digs)
{
const base_int* tptr = n.used > used ? n.data : data;
const base_int* bptr = tptr == data ? n.data : data;
const int tlen = tptr == data ? used : n.used;
const int blen = bptr == data ? used : n.used;
if(digs < 1)
digs = tlen + blen + 1;
base_int* new_data = new base_int[digs];
for(int i = 0; i < digs; ++i)
*new_data++ = 0;
for(int i = 0; i < blen; ++i)
{
int stop_pt = MIN(tlen, digs - i);
overflow_int carry = 0;
overflow_int btmp = bptr[i];
for(int j = 0; j < stop_pt; ++j)
{
overflow_int prod = btmp * tptr[j] + carry;
carry = prod >> BASE_BITS;
overflow_int sum = new_data[i + j] + carry + (prod & MAX_DIG);
carry += sum >> BASE_BITS;
new_data[i + j] = sum;
}
}
//delete[] data; these two lines cause the error
//data = new_data;
used = digs;
alloc = digs;
strip_zeros();
}
Notice the two lines I commented out. Without them the program executes and finishes (although now the result is incorrect). What is it about changing the value of a pointer or deleting it which could make my program have this strange error? Also I am pretty sure data is valid since I use it in the code above.
Also I am compiling with G++ through Netbeans.
After inspecting further it seems that the problem may be with my deconstructor. If I comment out the delete[] data in the deconstructor the error seems to go away. I don't know why.
BigInt::~BigInt()
{
if(data) delete[] data;
}
for(int i = 0; i < digs; ++i)
*new_data++ = 0;
This code is modifying where the new_data pointer is pointing at, so that it is no longer pointing at the original array when you enter the subsequent loop, or do anything with it for that matter. The pointer you pass to delete[] must be pointing at the same memory address that new[] returned.
The correct way to zero-initialize the array is to do this instead:
for(int i = 0; i < digs; ++i)
new_data[i] = 0;
Or, get rid of the loop and just use memset() instead:
memset(new_data, 0, digs * sizeof(base_int));
You must be very careful about matching up uses of new and delete. If you allocate something using the array form of new, you must delete it using the array form of delete. If you mix-and-match the array and non-array forms, you'll get crashes like this. You also must never delete something that wasn't allocated with new, and you must never delete the same thing twice.
I can't give you any more specific advice about this particular program, because you do not show us where the pointer named data is allocated.
I got it. I managed to screw up my new_data pointer.
for(int i = 0; i < digs; ++i)
*new_data++ = 0;
I changed it to this.
for(int i = 0; i < digs; ++i)
new_data[i] = 0;

meet exc_bad_access errror when operating on c-style string

I'm solving a problem that "replace all spaces in a string with ‘%20’." and I want to operate on the original string instead of create a new string. Here is my code:
void replaceSpaces(char* s, int len) {
int spaceCnt = 0;
for(int i = 0; i < len; ++i) {
if(s[i] == ' '){
++spaceCnt;
}
}
int newlen = len + 2 * spaceCnt;
s[newlen] = '\0';
for(int i = len - 1; i >= 0; --i) {
if(s[i] == ' ') {
s[newlen - 1] = '0';
s[newlen - 2] = '2';
s[newlen - 3] = '%';
newlen -= 3;
} else {
s[newlen - 1] = s[i];
--newlen;
}
}
}
And I have an "thread: exc_bad_access" error in the line s[newlen] = '\0';. I know it's dangerous to operate c-stye string in this way but I don't know how to modify it...
Any explanations or suggestions will be appreciated!
Well, if the original buffer is not long enough to contain the string with replacements, you are accessing memory out of bounds. When you determine the new size, you could do a realloc call to reallocate a suffiecient buffer with the size newlen like *s = realloc(*s, newsize). The only issue is that you need to change the paramter from char* s to char** s so that if realloc moves the memory to another block you update the pointer. And of course, this will work with strings allocated on heap, not local stack strings, since you can't reallocate that.

Deleting pointers from an array

I am fairly new to C++, and this problem I am having has had me stumped for like the last 2 hours. What I am trying to do is create an array of pointers to my class Word objects, so a 2 dimensional array, which is **wordPtrList. Then I need to delete the memory of certain objects in the array and set their pointers to null. I have written a smaller version of what I am trying to accomplish below.
int main()
{
char *cArray;
cArray = new char[4];
int i;
for (i = 0; i < 3; i++)
cArray[i] = 'a';
cArray[i + 1] = '\0'; //cArray is a null terminated string
Word **wordPtrList;
wordPtrList = new Word* [3];
for (i = 0; i < 3; i++)
{
wordPtrList[i] = new Word(cArray);
}
wordPtrList[1]->del();
delete wordPtrList[1];
wordPtrList[1] = '\0';
return 0;
}
class Word
{
private:
char* ptr_;
int len_;
public:
Word(const char* word)
{
len_ = strlen(word);
ptr_ = new char[len_];
strcpy(ptr_, word);
}
~Word()
{
delete [] ptr_;
ptr_ = 0;
}
void del()
{
delete [] ptr_;
ptr_ = 0;
return;
}
};
When I do this however, I get:
Debug Error Heap Corruption Detected after normal block
This is in VS 2010 on Windows 7.
So what I am asking is, how do I delete the memory of my object so that I can set wordPtrList[1] to Null?
You are allocating 4 bytes to cArray (meaning you have access to write to bytes 0 through 3), and then writing to cArray[4]. You also allocate one byte too small in the Word constructor.
char *cArray;
cArray = new char[4];
int i;
for (i = 0; i < 3; i++)
cArray[i] = 'a';
cArray[i] = '\0'; //cArray is a null terminated string - i is now 3
and
Word(const char* word)
{
len_ = strlen(word);
ptr_ = new char[len_ + 1];
strcpy(ptr_, word);
}
should do the trick.
Look at this code:
for (i = 0; i < 3; i++)
cArray[i] = 'a';
cArray[i + 1] = '\0'; //cArray is a null terminated string
The problem is at the last line which is using i+1 as index, which is going out of range, as by the time the loop exits, the value of i is already 3; that means i+1 will become 4 which cannot be a valid index when you've allocated cArray as:
cArray = new char[4]; //taken from your code
The solution is this:
cArray[i] = '\0'; //Now, it is correct. Here i is equal to 3
That is, use i instead of i+1; Or simply use 3.
In C++, you could std::fill instead of manual loop, as:
std::fill(cArray, cArray + 4, 'a'); //done
Even better avoid using char* with new as much as possible, and prefer using std::string instead.
There are two obvious off-by-one errors in the code (when you get out of the first loop what is the value of the variable i? when calling strlen did you remember to consider the space needed by the null terminator?).
Also please note that c strings are not "null terminated", they are "NUL terminated" with uppercase letters and only one "L". NUL is the name of the ASCII control character with all bits set to zero and is represented in C++ with '\0'.
In one place you used NUL character as a null pointer, and while this is technically correct (because of a design bug of the C++ language) it's better to understand that the two concepts are quite different.
As others have said, you're basically accessing an array index which is out of bounds of the array.
I would go with Nathan Wiebe's solution.
In the future, when you have the option to do this, it's recommended to use std::vector<T> as that will allow you to store any type you wish in a dynamically resizeble array. In other words, providing you don't access an index which is outside of the vector's bounds, you could do something like this:
std::vector< char* > str;
for( size_t i = 0; i < str.size(); ++i )
{
str.push_back( 'a pointer to a block of memory consisting of characters' );
}
class Word
{
public:
Word( const char* str )
{
mStrs.push_back( str );
}
~Word( void )
{
for( size_t i = 0; i < mStrs.size(); ++i )
{
if( mStrs[ i ] )
{
delete mStrs[ i ];
mStrs[ i ] = NULL;
}
}
mStrs.clear();
}
private:
void del( size_t index )
{
if( index > mStrs.size() )
{
//error - throw new exception or something
}
delete mStrs[ index ];
}
std::vector< const char* > mStrs;
};