I am having issues de-allocating memory that I used in my char* array. In my code snippet below, I am creating a char* array named input that holds pointers to single words at a time followed by a pointerNULL at the end of the array. This is the only time (I believe) I allocate memory in my code.
char* input[999];
//exec commands
for(unsigned int i = 0; i < commands.size(); i++)
{
string current = "";
string word = "";
int k = 0;
for(unsigned int j = 0; j < commands.at(i).size(); j++) //iterate through letters
{
current = commands.at(i);
//cout << "current: " << current << endl;
if(current[j] == ' ')
{
input[k] = new char[word.size() + 1];
strcpy(input[k], word.c_str());
k++;
word = "";
}
else
word += current[j]; //add letter
//cout << "word: " << word << endl;
}
input[k] = new char[word.size() + 1];
strcpy(input[k], word.c_str());
k++;
input[k] = new char[1]; //add the NULL char *
input[k] = NULL;
...
Later on, I attempt to de-allocate this memory with this snippet of code:
for(int z = 0; z < k; z++)
{
delete[] input[z];
}
I am iterating through my char* array and deleting the memory allocated at each index. Without using this snippet, valgrind informs me of memory leaks. Using this snippet, valgrind informs me of less memory leaks than before. I am still stuck with the issue of memory still being definitely lost.
I am unsure what I am missing to remove the rest of the allocated memory (or if the cause of the rest of the memory leaks is in fact somewhere else in my code). I appreciate any and all help, suggestions, and tips.
I think, your problem is in below case,
input[k] = new char[1]; //add the NULL char *
input[k] = NULL;
here, without free-ing input[k], you're assigning NULL to it. Thus, the previous input[k] is lost.
If you really want input[k] to hold NULL, (maybe as a sentinel value), you can simply do
input[k] = NULL;
No need to allocate memory separately.
You don't need to create a new char on where it says input[k] = new char[1]; //add the NULL char * Just leave the NULL assignment in and it should work fine.
Related
I'm trying to create a 2D array of c-strings (for a specific school exercise; I'm forced to use c-strings for practice) using dynamic memory allocation. However, it seems that when accessing and writing to the second index of the array (second sub-array), the actual memory location that's used is the same of the first index.
The code:
#include <iostream>
#include <string>
int main()
{
int n_names; std::string current; const int SPACE_FOR_EACH_NAME = 100;
std::cout << "How many names to input? "; std::cin >> n_names; std::cin.ignore();
//dynamically allocate a multi-dimensional array
char** names;
names = new char* [n_names];
for (int i = 0; i < n_names; i++)
names[i] = new char[SPACE_FOR_EACH_NAME];
int count = 0;
while (count < n_names) {
std::cout << "Name " << ++count << ": ";
std::getline(std::cin, current);
names[count-1] = (char*) current.c_str(); //THE TROUBLE SEEMS TO BE HERE
}
for (int i = 0; i < n_names; ++i) {
for (int j = 0; j < SPACE_FOR_EACH_NAME; ++j) {
if (names[i][j] == '\0') break; //termination of the current name
std::cout << names[i][j];
}
std::cout << "\n";
}
//free allocated memory
for (int i = 0; i < n_names; ++i)
delete[] names[i];
delete[] names;
}
What the debugger shows when modifying the 'names' array (consider user inputs 2 names):
+ names[count-1] 0x00affbe8 "dude" char * //here count is 1
+ names[count-1] 0x00affbe8 "noice" char * //here count is 2
And the console just prints "noice" twice.
What's wrong?
The result of current.c_str() should never be stored for any length of time. Doing so is undefined behaviour, but it is likely, as here that that memory pointed to will be reused.
You put the char* from current.c_str() into names[0], then you put a new value into current and put current.c_str() into names[1]. But because you have changed current you also change names[0].
Also, in both cases, you are discarding the pointer you already created with names[i] = new char[SPACE_FOR_EACH_NAME];
This allocates a block of memory and puts it's address into names[0] (0 as a specific example). The next thing that happens with names[0] is names[0] = (char*) current.c_str(); which puts a different address into the variable. The address returned from the new is lost completely, causing a memory leak.
Instead of
names[count-1] = (char*) current.c_str();
try
std::strcpy(names[count-1],current.c_str())
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;
}
I have to create a program that uses the 'new' operator to create a dynamic array in heap of the program. The program creates and populates its dynamic array one (int) elements at a time for each input data (cin).
Key parts.
1.) Program has to used "cin >>" for data input to accept on integer at a time until EOF is pressed on the keyboard (cntrl-z for windows).
2.) User input has to be tested using !cin.eof() && cin.good() to test whether or not the EOF key was pressed and if the data is valid. (kinda of confused about the cin.good() part).
3.) The program will create a series of longer and longer arrays to contain all previous elements and the current incoming one. Also, the program will delete the previous version of the array after completing the current version.
4.) The program also tests if heap memory has been exhausted after each use of the new operator. (need help with this)
I keep getting error message "HEAP CORRUPTION DETECTOR After normal black (#146)" (visual studio). What's the issue?
Thanks in advance!
Here's the code:
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cassert>
using namespace std;
// main
int main() {
int size = 2;
int * array1 = new int[size];
int arrayInput;
int count = 0;
do {
if (array1 != NULL) {
cout << "Enter an integer (EOF to stop): " << endl;
cin >> arrayInput;
if (size < count) {
int * tempArray;
tempArray = new int[size * 2];
if (tempArray != NULL)
{
for (int i = 0; i < size; i++) {
array1[i] = tempArray[i];
}
delete[] array1;
array1 = tempArray;
size *= 2;
delete [] tempArray;
}
else
cout << "Insufficient Heap resource." << endl; // If we get here the Heap is out of space
}
if (!cin.eof()) {
array1[count++] = arrayInput;
}
}
else
cout << "Insufficient Heap resource." << endl; // If we get here the Heap is out of space
} while (!cin.eof());
for (int i = 0; i < count; i++) {
cout << array1[i] << endl;
}
}
tempArray = new int[size * 2];
if (tempArray != NULL)
{
for (int i = 0; i < size; i++) {
array1[i] = tempArray[i];
}
You allocate a new array twice as big as your old array. Then you copy the contents of the newly allocated array into your existing array. The newly-allocated array contains random garbage, that you just used to override the existing, good data, in your old array.
That's one obvious bug, but it won't explain the crash.
delete[] array1;
array1 = tempArray;
size *= 2;
delete [] tempArray;
After copying, you delete your old array. Then you also delete your new array, that you just allocated. That smells like another bug, but it still won't explain the crash.
if (!cin.eof()) {
array1[count++] = arrayInput;
}
Now, you can answer your own question here: what happens when you continue to write to a pointer that was pointing to memory that you freed, recently?
That are multiple bugs in the shown code. They all must be fixed. I haven't looked further, past this point. There might still be other issues with this code. A rubber duck should be able to help you to find any remaining bugs in your program.
I need reverse my char string only with pointers. How can I do this? My code:
// this cannot be modified !!!
char s[10] = "abcde";
char *pS;
// my code
pS = new char;
int count = 5;
for (int i = 0; i < 10; i++)
{
if (s[i] != '\0') // not null
{
pS[count - 1] = s[i];
count--;
}
}
cout << "Reversed = " << pS;
Sometimes if works fine, I see only 5 chars, they are reversed. But sometimes I see some extra chars (looks like temp symbols). Where I miss something? Thank you!
your char array "s" contains 10 chars, but you only initialize the first 6 chars of that array with "abcde" and the \0 terminator.
When you loop over the complete array, you access not initialized chars.
I also see, that you try to write to memory, which you didn't allocate.
You only allocate memory for 1 char for you "pS" pointer, but you try to access it's memory like it is an array of chars in your for-loop.
Instead of using hardcoded:
int count = 5;
you also could use the string function strlen() to determine the length of the c-string.
Edited (untested code):
char s[10] = "abcde";
char pS[10];
for (int i = 0; i < strlen(s); i++)
{
if (s[i] == '\0') // not null
{
// stop loop, as soon as you reach the end of the original string
break;
}
pS[strlen(s) - 1 - i];
}
// now add the termination char \0 to your pS array
pS[strlen(s)] = '\0';
cout << "Reversed = " << pS;
Just giving you the hint how to reverse the string using pointers:
Take two pointers front and rear where front is pointing to first char of string and rear is pointing to last char of string.
Check if front is less than rear
If yes, swap the value of first and last character. If no , just print the string.
Increment front pointer and decrement rear pointer
Repeat from step 2.
After reading another book I fully understand pointers and how to correctly allocate memory. Here is my final code which correctly reverse array of char string (I don't need universal code, just working example + without std methods for reversing):
// not edited part - based on exercise (I mean I cannot change pS to char[5] etc.
char s[10] = "abcde";
char *pS;
pS = new char[strlen(s) + 1]; // allocate correct memory size based on string size
cout << "Size is " << sizeof(pS) << endl; // just for testing
int count = strlen(s); // for iteration
pS[count] = '\0'; // last symbol must be '\o' (thanks to Mr.Yellow)
for (int i = 0; i < 10; i++) // 10 because array of char still has 10 elements
{
if (s[i] != '\0') // looks like "not garbage memory"
{
count--;
pS[count] = s[i]; // set correct value
}
}
cout << "Reversed = " << pS << endl;
Thank you to all who helps me!
I'm learning to use pointer to copy char array.
I have the following code in C++. What I'm trying to do is to transfer and array (set1) using pointer to another pointer array (temp).
But when I try to print out (temp), it is not the same as (set1).
Transfer an array via pointer to another temp array pointer.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char set1[] = "ABC";
char* p = &set1[0];
int tempSize = 0;
char* temp = new char[256];
for (int i = 0; i < 3; i++)
{
*temp = *p;
cout << *temp; // ABC
++temp;
++tempSize;
++p;
}
cout << "\n";
for (int i = 0; i < tempSize; i++)
{
cout << temp[i]; // Why ABC is not printed?
}
delete [] temp;
return 0;
}
// Why ABC is not printed?
Because your pointer is travelling in undefined behavior region:
char* temp = new char[256];
...
++temp; // gone !!
On top of that,
you are not terminating the string with \0 in the end (may not be needed in your code)
delete[]ing this corrupt pointer in the end.
Since you are writing for learning purpose, I would suggest simple fix to your code:
char* const temp = new char[256];
^^^^^ ensures `temp` is not modifiable
Now use temp[i] for traversing purpose.
It's because in the loop copying the array, you change temp. After the loop, it points to one beyond the copied data.
Also, you forget to terminate the new allocated array. You should add the character '\0' at the end.
The problem is this line:
++temp;
You are incrementing the pointer and then write to it. In the end temp[i]; does not point to the beginning of your string, but to the end.
The easiest way to do this is to remove the first for loop with:
for (int i = 0; i < 3; i++)
{
temp[i] = set1[i];
}
temp[4] = '\0'; // don't forget to close the string
C-style strings have a null terminator - "ABC" contains four characters. Also, I'm not at all sure that the delete call on temp is valid - you have been incrementing it since it was 'newed'.