C++ new & delete and functions - c++

This is a bit unclear to me... So, if I have a function:
char *test(int ran){
char *ret = new char[ran];
// process...
return ret;
}
and then call it multiple times:
for(int i = 0; i < 100000000; i++){
char *str = test(rand()%10000000+10000000);
// process...
// delete[] str; // do i have to delete it here?
}
So the question is, do I have to use delete[] for each new[] call?

You don't have to. But if you don't delete memory you reserved with 'new' you will start running out of memory eventually (memory leak).

Yes you do, otherwise you'll have a memory leak.
It's not the greatest idea to allocate in one function and free in another, though. Why not allocate in the for loop and pass the pointer to test -- this keeps the new and delete together in the code.

The answer was already given, but as you tagged the question as C++, and not as C, this is how you probably want to do it in C++ (of course, there might be other reasons not to, but there is little chance).
vector<char> (int ran){
vector<char> ret(char);
// process...
return ret;
}
And to call it:
for(int i = 0; i < 100000000; i++){
vector<char> str = test(rand()%10000000+10000000);
// process...
}
No new, thus no delete thus no memory leak.
Actually, you also probably want to use std::string instead of char* (I used vector to give a more general example).
Don't worry of data that will be copied. The compiler will optimize it out.
Edit : ok, it might not optimize it out :) however there are big chances it will. And as long there is no performance issues, go for the simplest version.

Related

Receive SIGSEGV signal when using malloc for char * in Linux Qt Creator C++

When I run the following code to allocate memory for char * using malloc() on QT Linux C++, SIGSEGV is signaled after about 250 executions.
for(int i = 0; i < 10000; i++)
{
char * test = (char * )malloc(500);
test = "mas";
cout<<test<<endl;
}
I tried to use free() or delete() but they also trigger system signal.
What is the problem?
The main problem is that you're stepping on your malloc()'ed pointer. Stepping on it multiple times:
// Original test case
for(int i = 0; i < 10000; i++) {
char * test = (char * )malloc(500);
test = "mas"; // BAD!!!
// You've just stepped on your "malloc'ed" pointer with a *different pointer!!!!
cout<<test<<endl;
}
Here is an alternative. Note that you've also got to have some way to "remember" the pointer for each malloc(), so you can "free()" it at the appropriate time:
// Better:
for(int i = 0; i < 10000; i++) {
char * test = (char * )malloc(500);
if (test == NULL) {
cout << "malloc error!" << endl;
break;
}
strcpy (test, "mas");
cout<<test<<endl;
free (test);
}
You've changed the value of the pointer test. You need to use memcpy or the like to copy the value "mas" into the buffer.
Better yet, use std::string
This code:
test = "mas";
Doesn't do what you think it does. You think it copies the string "mas" in to the buffer pointed to by test. What it actually does is it changes what test points to. Instead of pointing to the memory you allocated with the malloc, now it points to a statically allocated char buffer.
When you're allocating memory with malloc or new you get only a pointer in return, so you have to approach to that differently - with functions like strcpy, strcmp (if you need to check equality of texts you can't compare only pointers either). Read more about pointers in any C++ book. It's possible to create texts without allocating memory explicitly, for example, this is legal:
const char *text = "my text";
But further modifications like you showed in question are not (notice const here, it gives us more safety). In this case text is created somewhere in memory by compiler itself (i'm simplifying things now) and only pointer is assigned. In that case you cannot modify that text (at least not safe).
Next thing, when you are allocating any memory you have to free it manually, at least in languages like C/C++ where memory management (garbage collectors etc.) don't really exist. If you'll skip that step you'll run into trouble (out of memory exceptions for example) faster than you think.
this statement:
test = "mas";
does not copy strings, but pointers.
To copy a string in C, use carefully strcpy(3) (often strncpyis better).
strcpy(test, "mas");
But you really should use (as Vinbot answered) std::string since you code in C++
Also, compile C++ code on Linux with g++ -g Wall (and C code with gcc -g -Wall) to get warnings and debug info. Learn how to use the gdb debugger and also valgrind
See also this answer to a related question.

delete[] causing heap corruption

I'm well aware that there are countless problems like this, but I searched for hours and couldn't understand what I did wrong so I would really appreciate your help. (I'm new to programming)
I need to create a dictionary manager of sorts as part of my homework but I seem to have a problem with deleting words.
I get an error message "...triggered a breakpoint".
The usual answer people get to this problem is that this is heap corruption caused by going out of bounds but I can't see if and how I caused this.
I already made something similar with bus info management and it worked perfectly so that makes me even more confused... (Obviously, I did not make the mechanism exactly the same, but even after looking at my previous code I couldn't isolate the problem)
I added the functions I believe are of concern,
The adding function:
void Add_Word(char**& dictionary, int& dictionary_size, char word[])
{
char** temp = new char*[dictionary_size + 1]; // Create a new array of appropriate size.
int i;
for (i = 0; i < dictionary_size; i++)
{
temp[i] = dictionary[i]; // Copy head pointers addresses for all existing items.
}
temp[i] = new char[strlen(word)]; // Add the space for the new word,
temp[i][strlen(word)] = '\0'; // mark its end
strcpy_s(temp[i], strlen(word) + 1, word); // then copy it.
// I'm really not so sure about what I should put in the buffer length but
// strlen(word) + 1 seemed to work... I know... not good, but strlen(word) alone caused a problem.
if (dictionary_size > 0)
delete []dictionary; // Delete previous head pointers array if there are any and
dictionary = temp; // reset the main pointer to the address of the new one.
dictionary_size++; // Finally, increase dictionary_size.
}
The deleting function:
void Delete_Word(char**& dictionary, int& dictionary_size, char* word)
{
// !!! This is where the crash thingy happens.
delete[] Search_For_Word(dictionary, dictionary_size, word); // Delete the word from the dictionary.
// Search_For_Word returns a pointer to the word it receives, from the dictionary.
char** temp = new char*[dictionary_size - 1]; // Create a new array of appropriate size.
int i;
for (i = 0; i < dictionary_size; i++)
{
if (dictionary[i][0])
temp[i] = dictionary[i]; // Copy the head pointers of the existing
// items to the new array except for the deleted word.
}
delete[] dictionary; // Delete previous head pointers array and
dictionary = temp; // reset the main pointer to the address of the new one.
dictionary_size--; // Finally, decrease dictionary_size.
}
EDIT: Any parts that are excessively inefficient or obviously broken are likely a result of me messing with my code trying to figure this out on my own (such as the calling 3 times to strlen mentioned (thanks again for that, kfsone...), or forgetting to +1 it for the '\0' to mark the end of a string
--actually, no, if we go by obvious you won't tell me my mistakes #.#).
As for the reason I'm dealing with char instead of strings and vectors please allow me to quote myself: "...as part of my homework". I just barely started programming. That, and I want to grasp the basics before moving on to using the more comfortable higher-up tools.
Change:
temp[i] = new char[strlen(word)]
To:
temp[i] = new char[strlen(word)+1]
Your code has several problems.
First, if you want to allocate a C-style string on the heap using new[], then you must pay attention to the terminating NUL character.
So, if you want to do a deep copy from a string word, then you must calculate enough room, considering strlen(word) + 1: the +1 is for the terminating NUL character.
e.g.:
// Original code (wrong):
//
// temp[i] = new char[strlen(word)];
//
// New code:
temp[i] = new char[strlen(word) + 1]; // consider terminating NUL (+1)
Moreover, following your code with explicit new[]s and delete[]s is not easy.
In modern C++, you may want to use convenient robust container classes like std::vector and string classes like std::string, instead of raw C-style pointers and strings.
You can simply store a list of strings using a std::vector<std::string>, and vector::push_back() method to add new strings to the vector. No need to complicate code with new[], delete[], strcpy_s(), etc.
And if you want to deep-copy strings, you can just use the simple natural overload of operator= for std::string, and copy constructors; e.g. std::string temp = word; will work just fine.
This is C++, why are you not using std::string instead of char buffers?
If you must use char buffer strings and the secure forms of strcpy_s know that the buffer length must always be the size of the destination buffer, never a strlen function. In your case it is a bit understandable since you created the buffer with the strlen function. But what you should do is set the value into a variable and then use that any time you need the buffer size.
Also, and where I think your bug is, you are writing temp[i][strlen(word)] = '\0'; But the actual indexes of the buffer go from 0 to strlen(word)-1 so you're writing outside the allocated memory.
The code is now working.
It was wrong all over.
I messed up pretty much any part that I could regarding the dynamic memory while trying to fix it before.
I initially didn't care about calling 3 times to strlen becuase it's just homework and a very small program but I guess it's better to get used to do things the right way...
I also dropped the copy which I evidently don't understand very well in favour of a simple for loop.
// Add function. The rest is cut.
int word_length = strlen(word);
temp[i] = new char[word_length + 1]; // Added +1 here.
temp[i][word_length] = '\0'; /* This was correct after all.
the word_length index is the correct ending.*/
for (int j = 0; j < word_length; j++) // copy replaced by for loop.
temp[i][j] = word[j];
// cut
}
void Delete_Word(char**& dictionary, int& dictionary_size, char* word)
{
delete[] Search_For_Word(dictionary, dictionary_size, word);
// There was a -1 mistake here I made in order to try and fix the thing earlier.
// No need for more, it works perfectly now.

Resizing dynamic string array

I am trying to resize a dynamically allocated string array; here's the code!
void resize_array() {
size_t newSize = hash_array_length + 100;
string* newArr = new string[newSize];
fill_n(hash_array,newSize,"0"); //fills arrays with zeros
memcpy( newArr, hash_array, hash_array_length * sizeof(string) );
hash_array_length = newSize;
delete [] hash_array;
hash_array = newArr;
}
unfortunately it isn't working and gives a segmentation fault. any idea why? this is basically a linear probing hash table where the element gets inserted wherever there is a 0 hence I use fill_n to fill the newly created array with 0's. any help please?
memcpy( newArr, hash_array, hash_array_length * sizeof(string) );
This line is extremely dangerous, std::string is not a plain old data type,
you can't make sure that memcpy could initialize it correctly, it may cause
undefined behavior, one of the most nasty behavior of c++(or programming).
Besides, there are a better and safer(in most of the times) solution to create
a dynamic string array in c++, just use vector
//create a dynamic string array with newSize and initialize them with "0"
//in your case, I don't think you need to initialize it with "0"
std::vector<std::string> newArr(newSize, "0");
if the hash_array has the same type as newArr(std::vector)
The way of copy it is very easy.
c++98
std::copy(hash_array.begin(), hash_array.end(), newArr.begin());
c++11
std::copy(std::begin(hash_array), std::end(hash_array), std::begin(newArr));
Better treat c++ as a new language, it has too many things are different from c.
Besides, there are a lot of decent free IDE, like code::blocks and QtCreator
devc++ is a almost dead project.
If you are new to c++, c++ primer 5 is a good book to start.
If string is actually an std::string (and probably even if it isn't) then this will crash. You are creating a new array of strings, copying the old string classes over the top, and then freeing the old strings. But if the string class contains internal pointers to allocated memory this will result in a double free because all you are doing is copying the internal pointers - not making new memory allocations.
Think about it like this; imagine you had the following class:
class foo
{
char* bar;
foo() { bar = malloc(100); }
~foo() { free(bar);
};
foo* ptr1 = new foo;
foo* ptr2 = new foo;
memcpy(ptr2, ptr1, sizeof(foo*));
delete ptr1;
At this point, ptr2->bar points to the same memory that ptr1->bar did, but ptr1 and the memory it held has been freed
The best solution would be to use a std::vector because this handles the resizing automatically and you don't need to worry about copying arrays at all. But if you want to persist with your current approach, you need to change the memcpy call to the following:
for (int i = 0; i < hash_array_length; ++i)
{
newArr[i] = hash_array[i];
}
Rather than just copying the memory this will call the class's copy constructor and make a proper copy of its contents.
I suspect the culprit is memcpy call. string is complicated type which manages the char array by pointers (just as you are doing right now). Normally copying string is done using assignment operator, which for string also copies its own array. But memcpy simply copies byte-per-byte the pointer, and delete[] also deletes the array managed by string. Now the other string uses deleted string array, which is BAAAD.
You can use std::copy instead of memcpy, or even better yet, use std::vector, which is remedy to most of your dynamic memory handling problems ever.

How to use delete[] when pointer outside memory allocation?

Note that the question has been changed and no longer matches the answers
I'm trying to create memory to hold a buffer of floats (here, 4 floats).
I've allocated the memory, and all the 4 values in the memory are zero.
The loop of course iterates 4 times, but the 4th time moves ptr to outside the memory that I've allocated. So at the end of the loop I move ptr back to where I allocated the memory, and use delete[].
My question is: Is the entire 4-float buffer being deleted when I call delete[]? (this is obviously what I need!)
int inFramesToProcess = 4;
float *ptr = new float[inFramesToProcess]();
for(UInt32 i = 0; i < inFramesToProcess; ++i) {
ptr++;
}
ptr -= inFramesToProcess;
delete[] ptr;
Copy the pointer before you increment it.
int inFramesToProcess = 4;
float *ptr = new float[inFramesToProcess]();
float *ptr_copy = ptr;
for(UInt32 i = 0; i < inFramesToProcess; ++i) {
ptr_copy++;
}
delete[] ptr;
Or just don't use pointers for dynamic arrays, use a vector instead. Then you don't have to worry about deleting.
You can't.
You can only delete the value you get from new. Keep the original pointer.
General rule:
Try hard to avoid modifying pointers at all times, no matter how clever/professional/"brilliant" it looks. There's really no reason to (you're welcome to prove me wrong). Use subscripts instead; they're more readable and easier to debug, and they avoid these kinds of issues.

Is delete p where p is a pointer to array always a memory leak?

following a discussion in a software meeting I've set out to find out if deleting a dynamically allocated, primitives array with plain delete will cause a memory leak.
I have written this tiny program and compiled it with visual studio 2008 running on windows XP:
#include "stdafx.h"
#include "Windows.h"
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*1000; i++)
{
int* p = new int[1024*100000];
for (int j =0;j<BLOCK_SIZE;j++) p[j]= j % 2;
Sleep(1000);
delete p;
}
}
I than monitored the memory consumption of my application using task manager, surprisingly the memory was allocated and freed correctly, allocated memory did not steadily increase as was expected
I've modified my test program to allocate a non primitive type array :
#include "stdafx.h"
#include "Windows.h"
struct aStruct
{
aStruct() : i(1), j(0) {}
int i;
char j;
} NonePrimitive;
const unsigned long BLOCK_SIZE = 1024*100000;
int _tmain()
{
for (unsigned int i =0; i < 1024*100000; i++)
{
aStruct* p = new aStruct[1024*100000];
Sleep(1000);
delete p;
}
}
after running for for 10 minutes there was no meaningful increase in memory
I compiled the project with warning level 4 and got no warnings.
is it possible that the visual studio run time keep track of the allocated objects types so there is no different between delete and delete[] in that environment ?
delete p, where p is an array is called undefined behaviour.
Specifically, when you allocate an array of raw data types (ints), the compiler doesnt have a lot of work to do, so it turns it into a simple malloc(), so delete p will probably work.
delete p is going to fail, typically, when:
p was a complex data type - delete p; won't know to call individual destructors.
a "user" overloads operator new[] and delete[] to use a different heap to the regular heap.
the debug runtime overloads operator new[] and delete[] to add extra tracking information for the array.
the compiler decides it needs to store extra RTTI information along with the object, which delete p; won't understand, but delete []p; will.
No, it's undefined behavior. Don't do it - use delete[].
In VC++ 7 to 9 it happens to work when the type in question has trivial destructor, but it might stop working on newer versions - usual stuff with undefined behavior. Don't do it anyway.
It's called undefined behaviour; it might work, but you don't know why, so you shouldn't stick with it.
I don't think Visual Studio keeps track of how you allocated the objects, as arrays or plain objects, and magically adds [] to your delete. It probably compiles delete p; to the same code as if you allocated with p = new int, and, as I said, for some reason it works. But you don't know why.
One answer is that yes, it can cause memory leaks, because it doesn't call the destructor for every item in the array. That means that any additional memory owned by items in the array will leak.
The more standards-compliant answer is that it's undefined behaviour. The compiler, for example, has every right to use different memory pools for arrays than for non-array items. Doing the new one way but the delete the other could cause heap corruption.
Your compiler may make guarantees that the standard doesn't, but the first issue remains. For POD items that don't own additional memory (or resources like file handles) you might be OK.
Even if it's safe for your compiler and data items, don't do it anyway - it's also misleading to anyone trying to read your code.
no, you should use delete[] when dealing with arrays
Just using delete won't call the destructors of the objects in the array. While it will possibly work as intended it is undefined as there are some differences in exactly how they work. So you shouldn't use it, even for built in types.
The reason seems not to leak memory is because delete is typically based on free, which already knows how much memory it needs to free. However, the c++ part is unlikely to be cleaned up correctly. I bet that only the destructor of the first object is called.
Using delete with [] tells the compiler to call the destructor on every item of the array.
Not using delete [] can cause memory leaks if used on an array of objects that use dynamic memory allocations like follows:
class AClass
{
public:
AClass()
{
aString = new char[100];
}
~AClass()
{
delete [] aString;
}
private:
const char *aString;
};
int main()
{
AClass * p = new AClass[1000];
delete p; // wrong
return 0;
}