How do I allocate memory with "new" instead of malloc? - c++

As a homework I have to write a program that operates around structures. As a first task i have to write a function that allocates memory for an array of N pointers that point to new structures(user decides about the value of N) and returns the adress of an array. The first problem that i have is understanding the form of malloc. I asked my professor what would be the equivalent by using "new" because it is more transparent for me but he answered that I should stick to malloc so i avoid making any mistakes. The following function looks like this:
struct Structure
{
int a;
char b;
float c;
};
Structure** allocating(int N)
{
struct Structure** tab = (struct Structure**) malloc(amount * sizeof(struct Structure*));
for (int i = 0; i < N; i++)
{
tab[i] = (struct Structure*) malloc(sizeof(struct Structure));
}
return tab;
}
I have tried understanding this form of allocating memory but so far i understand this as if i was allocating memory for a pointer pointing to the array of pointers(double **) which is not what was stated in a task. To sum up, i don't understand the way the allocating is written and how could it be written by using new.

Your C code allocates an array of pointers to Structure. I have no idea why it is done this way instead of simply allocating an array of Structure, you have to ask the author of the task for that.
Direct equivalent using new would look like this :
Structure** allocating(int N)
{
struct Structure** tab = new Structure*[N];
for (int i = 0; i < N; i++)
{
tab[i] = new Structure;
}
return tab;
}
Deallocating can be a bit tricky:
void deallocating(Structure** tab, int N)
{
for (int i = 0; i < N; i++)
{
delete tab[i]; //delete objects
}
delete[] tab; //delete array itself, notice the [] after delete!
}
If you can move to array of objects instead of array of pointers, the code gets much simpler:
Structure* allocating(int N)
{
return new Structure[N];
}
Later you also deallocate it with delete[]
As noticed in comments, in C++ we prefer to not use memory management directly (especially in modern C++ keyword new is considered to be a bad smell). std::vector can handle all your array-on-the-heap needs perfectly well, it will never leak memory and can resize itself easily.

Related

Shrinking the size of a dynamically allocated array in C++ [duplicate]

I have created an array pointer as a global variable like this:
T *bag;
bag = new T[size];
I have a method where I insert things into the array; however, if it detects that it will overflow the array, I need to resize the array (without vectors). I've been reading about this question all over stack overflow but the answers don't seem to apply to me because I need the data from the old array copied into the new array. Additionally, if I create a new array of a larger size inside the method and then copy the data over to the new array, once the method ends, the array will disappear, but I need it to be a global variable again so all my methods can see it...How should I proceed?
Thank you
Memory, allocated by new, would not disappear after your method ends.
You can return pointer to a new array by usung reference: void f(int *&ptr, size_t &size).
Also, be aware, that you need to clear memory manually arter you use it. For example:
int* newArray = new int[newSize];
... copying from old array ...
int* temp = oldArray;
oldArray = newArray;
delete[] temp;
To resize an array you have to allocate a new array and copy the old elements to the new array, then delete the old array.
T * p_bag;
p_bag = new T[old_size];
//...
T * p_expanded_bag = new T[new_size];
for (unsigned int i = 0; i < old_size; ++i)
{
p_expanded_bag[i] = p_bag[i];
}
delete[] p_bag;
p_bag = p_expanded_bag;
You could use std::copy instead of the for loop.
The thing you need can do the following things
Automatically handle the resizing when requested size is larger than current array size.
When resizing, they can copy the original content to the new space, then drop the old allocation immediately .
There is a non-global-variable way mechanism they can track the array pointer and the current size.
The thing is very similar to std::vector. If it is not allowed to use, you may need manage a dynamic allocated resource like std::vector on your own. You can reference the implementation in that answer link.
If eventually you need to wrap it in a class, make sure to follow the big 3 rules (5 rules in C++11)
You can use realloc from c if you have array of chars/ints/doubles... or some other fundamental data type or classes with only those variables (eg. array of strings won't work).
http://www.cplusplus.com/reference/cstdlib/realloc/
bag = (T*) realloc(bag, new_size * sizeof(T));
Realloc automatically allocate space for your new array (maybe into the same place in memory) and copy all data from given array.
"The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location."
Example:
#include <stdio.h> /* printf*/
#include <stdlib.h> /* realloc, free */
#include <iostream>
int main()
{
int old_size = 5;
int new_size = 10;
int *array = new int[old_size];
printf("Old array\n");
for (int i=0; i<old_size; i++) {
array[i] = i;
printf("%d ", array[i]);
}
printf("\nArray address: %d\n", array);
array = (int*) realloc(array, new_size * sizeof(int));
printf("New array\n");
for (int i=0; i<new_size; i++)
printf("%d ", array[i]);
printf("\nArray address: %d\n", array);
free(array);
return 0;
}

Free dynamic array of static arrays?

I have code similar to this
EDIT this code is supposed to be on interface so only POD is allowed. No vectors, no containers.
int (*neco)[2];
int ahoj = 2;
neco = new int[ahoj+2][2];
int iter = 1;
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 2; j++)
{
neco[i][j] =iter;
iter++;
}
}
for (size_t i = 0; i < ahoj + 2; i++)
{
delete[] neco[i];
}
This does not work. The delete deletes memory not allocated.
Not even
delete[] neco;
Or any other delete. Everyone of them deletes memory BEFORE the allocated block.
Googling and consulting with peers in the office had no results. :)
How do I allocate dynamic array of "points" (two coordinates) and then free them?
I am able to solve the problem via using different structure.
But apperently I am able to allocate the memory. Write in the allocated memory…
How do I correctly free this memory? (Just accademic question.)
Plain pointers to dynamically allocated memory get you into troubles.
Use a std::unique_ptr:
#include <memory>
// ...
std::unique_ptr<int[][2]> neco(new int[ahoj+2][2]);
And remove that loop with delete[].
Alternatively, use std::vector<int[2]> neco(ahoj+2) - it does memory management for you and can be resized.
The general rule is that every new expression must be matched by a single corresponding delete expression.
Your new expression is the right hand side of the statement
neco = new int[ahoj+2][2];
so the corresponding delete expression is given in the statement
delete [] neco;
If that doesn't work (which is what you claim) it means the problem is in some other code exhibiting undefined behaviour.
Your loop
for (size_t i = 0; i < ahoj + 2; i++)
{
delete[] neco[i];
}
is incorrect because none of the neco[i] are the result of a new expression. So delete [] neco[i] has undefined behaviourin every loop iteration.
Given that your code sample(s) and description are incomplete, I doubt anyone else can give more useful advice.
Also, you are mistaken in your belief that you can't use a standard container. You can.
#include <vector>
int main()
{
std::vector<int[2]> avec(ahoj + 2);
int (*neco)[2] = &avec[0];
for (size_t i = 0; i < ahoj + 2; ++i)
{
for (size_t j = 0; j < 2; ++j)
{
neco[i][j] = iter;
++iter;
}
}
}
The only difference is that avec does the dynamic memory allocation and deallocation for you. neco is still a pointer to an array as required (according to your description) by your API. The two constraints on this approach are;
don't resize theavec after initialising neco (or reinitialise neco whenever avec is resized)
don't use neco after avec ceases to exist (since the behaviour will then be undefined).
Also, none of the arrays are actually static. So your question is mistitled.
If I can recall properly, an array of arrays (being dynamic or static), is basicly a matrix.
So, the academic answer:
The same way you allocate memory (first allocate the memory of the array of arrays, then with a foryou allocate the memory of the arrays inside the array), to free it, you need to delete in a forthe memory of the arrays, and then, in a simple delete, free the memory of the dynamic array.
So:
arrayOfArrays[[array1][array2][array3][array4]]
means: allocate memory of arrayOfArrays, then in a loop, allocate memory of array(number)
Same goes the other way around.
Free memory of arrayOfArraysin a single sentence.

Array of doubles and heap corruption

I have a function like
template <class Type>
myFunc(Type** arrayToBeFilled);
I call it like this:
double* array = NULL;
myFunc(&array);
And inside the function I do some reading and parsing numbers with strtod function:
//Here comes file opening, getting number of lines and number of doubles in every line
...
char *inputString = new char[LONG_STRING_SIZE];
char *pNext = NULL;
(*arrayToBeFilled) = new Type[length*rowSize];
for (int i=0; i<length; i++)
{
source.getline(inputString, LONG_STRING_SIZE);
pNext = NULL;
for (int j=0; j<rowSize; j++)
{
double d = strtod(inputString, &pNext);
(*arrayToBeFilled)[i*rowSize+j] = d;
inputString = pNext;
pNext = NULL;
}
}
Variable d is just for check with debugger - and it's just fine while running.
But after filling the array I try to print it (just for check)
for (int i=0; i<length; i++)
{
for (int j=0; j<rowSize; j++)
{
cout<<(*arrayToBeFilled)[i*rowSize+j]<<" ";
}
cout<<"\n";
}
And here comes bad output - other numbers, sometimes heap corruption and so. I was printing it in and out of the function - the same results. And I can't delete this array no or neither out the function - run time errors follow me!
Why do you use raw C arrays in C++? If you use STL classes like std::vector instead of raw new[], your code will become cleaner, simpler to read and maintain (for example, you don't need explicit delete[] calls: the destructor will cleanup heap memory). In general, in modern C++ the rule is "if you are writing new or delete, you are doing it wrong" (with some exceptions).
Note also that with C++11 move semantics, you can simply return the vector instead of using output reference/pointer arguments:
template <typename Type>
inline std::vector<Type> myFunc()
{
...
}
Inside your function body, instead of your code
(*arrayToBeFilled) = new Type[length*rowSize];
just write:
std::vector<Type> arrayToBeFilled(length*rowSize);
and then simply return arrayToBeFilled; .
(Note also that vector's can be nested together: you may also use vector<vector<Type>> to make a 2D array, but this is less efficient than a single vector<Type>, which more directly maps to your raw new[] call.)
In addition, in the code you posted you create a raw C array on the heap with new char[LONG_STRING_SIZE] and assign the pointer to it to inputString; then you modify inputString with an assignment from pNext: but in doing so, you leak the initial array whose pointer was stored in inputString.
Seems you don't have a return type
template <class Type>
void myFunc(Type** arrayToBeFilled);
and you should initialize your function
double array = NULL;
myFunc<double>(&array);
also when it comes to input, print out the values that you get, more often than not you may get something unexpected which causes the error.

C++ array of pointer memory leaks

In my class I have a dynamically allocated array of pointers. My declaration:
array = new Elem* [size];
for (int i = 0; i < size; i++) {
array[i] = NULL;
}
So there is an array of pointers, where each pointer points to a simple Elem struct.
The main question is, how should I properly deallocate the array. If I use only:
for (int i = 0; i < size; i++) {
delete array[i];
}
Valgrind reports 1 not-freed block, which is traced to the line where 'array = new Elem* [size];' states.
On the other hand if I add to the previous code:
delete array;
Which I thought is correct, valgrind reports 0 not-freed blocks, which is perfect, BUT it reports
Mismatched free() / delete / delete []
exactly on the line where 'delete array;' is. I tried 'delete []array' too, but that's just "1 not-freed blocks" too then! If somebody could explain me the proper way it would be much appreciated.
EDIT:
So using:
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
is working probably fine. It is working in one of my classes (I have two similar) the other still reports some small leak. I would think it's just a minor bug somewhere, but valgrind still points to the line where
array = new Elem* [size];
stands.
EDIT2:
I solved this as well, thank you for your exhausting contribution!!
You need:
delete [] array;
Because it's an array.
I just noticed your note that you tried this too - it's the proper thing to do so I don't know why you'd still be getting an error.
Edit: This deserves a more thorough explanation.
When you create a pointer using new, the pointer may be to a single element or an array of elements depending on the syntax you use. But the pointer type is the same in both cases! The compiler relies on you to know what the pointer points to and treat it accordingly.
Elem ** single = new Elem*; // pointer to one pointer
single[0] = new Elem; // OK
single[1] = new Elem; // runtime error, but not compile time
Elem ** array = new Elem* [2]; // pointer to array of pointers
array[0] = new Elem; // OK
array[1] = new Elem; // OK
When you delete a pointer, the destructor is called for the object it points to or for each element of the array. But since the pointer type is the same in each case, the compiler relies on you to give it the proper syntax so it knows what to do.
delete single;
delete [] array;
In your case the elements of the array are pointers also, and pointers don't have destructors. That means those pointers won't be deleted and will become memory leaks if you don't delete them first. You were correct to have a loop to delete them individually before the final delete.
You should free everything in the array (if dynamically allocated) and then free the array itself.
for (int i = 0; i < size; i++) { // only free inside if dynamically allocated - not if just storing pointers
delete array[i];
}
delete[] array; // necesarry
The syntax for deleting an array is like this:
delete[] array;
Your for loop to delete the objects pointed to by the elements of the array is fine. The deletion of the array itself is the only problem. You need both the for loop and then the delete[] to dispose of the array itself.
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
I suspect that you have tried using the for loop, or the delete[], but not both together. And if when you do that you still have leaks or errors, then you would need to show us the code that allocates the pointers that are elements of the array.
Using std::vector<> instead of an array would mean that you could stop worrying about these nitty gritty details and move to higher level of abstraction.
In this case, you need both.
for (int i = 0; i < size; i++) {
delete array[i];
}
delete[] array;
You call delete exactly once for each time you called new.
Note that although you need to call delete[] array here (because you allocated it with new[]), the delete[] operator does not call the destructors on the objects pointed to by elements of the array. This is because the delete[] operator calls destructors on objects in the array, and your array contains pointers but not objects. Pointers do not themselves have destructors.

Filling an array of pointers, deleting when exiting

In C++, Lets say I'm creating an array of pointers and each element should point to a data type MyType. I want to fill this array in a function fillArPtr(MyType *arPtr[]). Lets also say I can create MyType objects with a function createObject(int x). It works the following way:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
Is it the best way to do it? In this program how should I use delete to delete objects created by "new" (or should I use delete at all?)
Since you asked "What is the best way", let me go out on a limb here and suggest a more C++-like alternative. Since your createObject is already returning objects by value, the following should work:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
Now you don't need to do any memory management at all, as allocation and clean-up is done by the vector class. Use it like this:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
Do say if you have a genuine requirement for manual memory management and for pointers, though, but preferably with a usage example.
Your method places the array of pointers on the stack, which is fine. Just thought I'd point out that it's also possible to store your array of pointers on the heap like so. Youd do this if you want your array to persist beyond the current scope
MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
If you do this, don't forget to delete the array itself from the heap
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
If you're going to use vector, and you know the size of the array beforehand, you should pre-size the array. You'll get much better performance.
vector<MyType*> arr(10);
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
I suggest you look into boost shared_ptr (also in TR1 library)
Much better already:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
Shooting for the stars:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
You would basically go through each element of the array and call delete on it, then set the element to 0 or null.
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
Another way to do this is with an std::vector.
Use an array of auto_ptrs if you don't have to return the array anywhere. As long as you don't make copies of the auto_ptrs, they won't change ownership and they will deallocate their resources upon exiting of the function since its RAII based. It's also part of the standard already, so don't need boost to use it :) They're not useful in most places but this sounds like a good one.
You can delete the allocated objects using delete objPtr. In your case,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
The rule of thumb to remember is, if you allocate an object using new, you should delete it. If you allocate an array of objects using new[N], then you must delete[] it.
Instead of sticking pointers into a raw array, have a look at std::array or std::vector. If you also use a smart pointer, like std::unique_ptr to hold the objects within an std::array you don't need to worry about deleting them.
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
You don't need to worry about deleting those when you're done using them.
Is the createObject(int x) function using new to create objects and returning a pointer to this?. In that case, you need to delete that as well because in this statement
new MyType( createObject(i++) )
you're making a copy of the object returned by createObject, but the original is then leaked. If you change createObject also to return an std::unique_ptr<MyType> instead of a raw pointer, you can prevent the leak.
If createObject is creating objects on the stack and returning them by value, the above should work correctly.
If createObject is not using new to create objects, but is creating them on the stack and returning pointers to these, your program is not going to work as you want it to, because the stack object will be destroyed when createObject exits.