Assigning dynamically allocated array of pointers - c++

Having a lot of trouble with this after sifting through many posts on here. Everything compiles but I get a crash right here during this function which should be dynamically allocating the addresses of one array into this array of pointers. I see one or two memory addresses posted so I'm not sure why it would be crashing during the middle of this.
string *copyArray(string ptrArray[],int sizeArray)
{
string **dynamString = new string*[sizeArray];
int i;
for (i=0;i<=sizeArray;++i)
{
(*dynamString[i]) = ptrArray[i];
cout << dynamString[i];
}
return *dynamString;
}
from main I have:
string *arrPtr;
and the function call
arrPtr = copyArray(arrayOfStrings, arraySize);

for (i=0;i<=sizeArray;++i)
accesses an element behind the array yielding an undefined behavior. Elements are indexed from 0 to sizeArray - 1. Another problem is that you allocate the array of pointers:
string **dynamString = new string*[sizeArray];
and then you are derefencing these pointers although they do not point to any object yet:
(*dynamString[i]) = ptrArray[i];
which also causes an undefined behavior. In case you wanted to create a deep copy, you should allocate the memory for every object as well:
for (i = 0; i < sizeArray; ++i)
{
dynamString[i] = new std::string(ptrArray[i]);
cout << *dynamString[i];
}
However you should avoid using C-style arrays always when it is possible and prefer STL containers instead. In this case it could be neat std::vector<std::string> and its constructor that would do the same than your function (just in safer and more reasonable manner with no possible memory leaks):
std::vector<std::string> myStrings(arrayOfStrings, arrayOfStrings + arraySize);

ok I fixed it here. My pointer syntax was incorrect. Here is the correct syntax.
dynamString[i] = &ptrArray[i];

Related

dynamic memory allocation c++

I have the following dynamically allocated array
int capacity = 0;
int *myarr = new int [capacity];
What happens if I do something like this:
for (int i = 0; i < 5; ++i)
myarr[++capacity] = 1;
Can this cause an error if the for loop is executed many times more than 5? It worked fine for small numbers, but I'm wondering If this is maybe a wrong approach.
You are setting memory outside of the bounds of the array. This might overwrite memory being used in another part of the program, it is undefined behavior. To fix this you should declare your array like this:
int* myArray = new int[5];
which will make it so you don't allocate out of the bounds of the array.
However, it is better to use std::vector. It will prevent situations like this from occurring by managing memory itself. You can add items to a std::vector like this:
Vector.push_back(myItem);
and you can declare a vector of ints like this:
std::vector<int> Vector;
You can read more about std::vector here.
It will cause out of bounds access. This is just undefined behaviour. Your program may crash, your car may not start in the morning, you see the pattern here.
It happens to work fine in your case because usually the OS allocates more than you ask it for, usually in multiples of 2, so probably here it allocates like 8/16..256 bytes at least. But you should not rely on this kind of behaviour.
EDIT The car issue was (almost) a joke, however undefined behaviour really means undefined. C++ standard decided to not enforce compiler checking of many of such issues, because checking takes time. So it declares the behaviour as Undefined Behaviour (UB). In this case, absolutely nothing is guaranteed. If you work e.g. on some small embedded system that controls the rudder of a plane, well, you can guess what may happen.
This approach is wrong in c++. Allocating memory with new allocates memory for new "capacity" objects that you can access without running in run-time error.
Here is a better way to manage the raw array in c++:
int capacity = 10;
int *myarr = new int [capacity];
for (int i = 0; i < 20 ; ++i) {
if (capacity < i) {
// allocate more memory and copy the old data
int *old_data = myarr;
myarr = new int [capacity * 2]
for (int j = 0; j < capacity; ++j) {
myarr[j] = old_data[j];
capacity *= 2;
}
delete [] old_data;
}
myarr[i] = 1;
}
And its always better to call delete []at the end. Another way to use pre-made dynamic array in c++ is to use the std:array(supported in c++11) or std::vector(or legacy support and the preferred option as of me) library which automatically reallocates more memory.
More for the vector and array and examples here for vector here
and here
for std::array.

Using functions from an objet inside an array of pointers

How would it be possible to use tabEmployes[0].Function ???
CEmploye **tabEmployes[NB_EMPLOYES] = new CEmploye[NB_EMPLOYES];
int main()
{
for (int i = 0; i < NB_EMPLOYES - 1; i++)
{
int j = 0;
string sNom = *LES_EMPLOYES[i, j];
int iNum = atol(*LES_EMPLOYES[i, j + 1]);
int iNiv = atol(*LES_EMPLOYES[i, j + 2]);
CEmploye* unEmploye = new CEmploye(sNom, iNum, iNiv);
tabEmployes[i] = &unEmploye;
}
tabEmployees is an array of pointers to pointer. This means that tabEmployees[0] is a pointer to a pointer. To access the class methods you would have to dereference the pointer. You could use
(*(tabEmployees[0]))->methodName();
However, your current code points tabEmployees[0] to the memory address of a local variable, which will go out of scope at the end of the loop. This is undefined behavior and will most likely lead to undesired results (such as a crash, or all your pointers being the same).
I think you don't really want tabEmployees to be an array of pointers to pointers, especially as your code shouldn't compile right now.
This line:
CEmploye **tabEmployes[NB_EMPLOYES] = new CEmploye[NB_EMPLOYES];
should not compile, as you are assigning an array of pointers to an array of pointers to pointers.
As you are creating your pointers during the loop, it seems to me you don't need to assign any value to this array. If you change it to:
CEmploye **tabEmployes[NB_EMPLOYES];
Your code will now compile.
However, as I said above, you still have the problem that you are pointing to a local variable that will be going out of scope. I would suggest that your tabEmployees should be defined as:
CEmploye *tabEmployes[NB_EMPLOYES];
and assigned later as
tabEmployes[i] = unEmploye;
(note the removed &).
Now your array contains pointers to the newly allocated objects, rather than to the variable that pointed to that object. You would then access methods as follows
tabEmployes[i]->methodName();

How can we modify the size of array in C++?

I have an array of characters allocated with new and i want to modify the size of the array. Can i use realloc function for that? What is the best way to do so?
No, you can't... realloc() can only be used with malloc()/free()
Best call for a new[] allocated array is to create a new one and then memcpy() the data from one to another.
Better way - use an std::vector or std::string instead of array if you know you'll need resizing. Internally they're pretty much the same array.
In C++ it is best to use the STL std::vector class for this kind of thing. Either that, or a std::string.
I have an array of characters allocated with new and i want to modify the size of the array.
You can't resize an array, you can only allocate a new, larger one, move the contents to the new array, and delete the old one.
Can i use realloc function for that?
If you used malloc to allocate the original array, yes. But that's usually a bad idea in C++, where you usually want to deal with arrays of non-trivial objects not raw memory.
What is the best way to do so?
Use std::string (or perhaps std::vector<char>) to manage a dynamic array of characters automatically. These also have the advantage of using RAII to reduce the risk of memory leaks and other memory management errors.
You can use realloc(), if your array is allocated dynamically(via malloc/calloc/realloc). If you have static array, you can't resize it.If you have allocated with new:
int* Copy = new int[newSize];
std::copy(oldCopy,oldCopy+size,Copy);
But the best way would be to use std::vector<type> from c++ standard library
As was said by others, you cannot resize the array that was allocated per se, but you can create a larger one, copy the content of the first array to the second and delete the first one.
Here's an example, using std::copy().
int main(int argc, char** argv) {
int* arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
int* tmp = new int[10];
std::copy(arr, arr + 5, tmp);
std::copy(arr, arr, tmp + 5);
delete[] arr;
arr = tmp;
for(int i = 0; i < 10; i++) {
std::cout << arr[i] << "\n";
}
delete[] arr;
std::cin.get();
return 0;
}
This first creates an integer array and fills it. It then creates a larger array and fills it with the content of the first array twice and display that new larger array.
The principle is the same for an array of characters.
As the others have mentionned, your best bet in C++ is to use the standard library. For a resizable array of characters, you should probably use std::string or a vector of strings, but it's a bit overkill in some situations.

Create pointer to pointer in while statement issue

in Visual Studio 2010 i create a while statement in which i assign a pointer to pointer to a map.
Example:
std::map<int,std::tuple<int,std::string>** > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = &t;
dmap[i + 1 ] = &t;
i++;
}
.
.
.
for (auto it = d.begin();it!=d.end();++it)
{
if(*(it->second) != nullptr){
delete *(it->second);
*(it->second) = nullptr;
}
}
The problem is that the address of &t is always the same and so at the end the map always contains , for all keys that i entered, the last *t value.
What's the problem? (Resolved)
[Edit]
Now i modify the code beacause before it was incomplete, if i want to avoid to delete nullptr i need to have a pointer to pointer. Or not?
The problem is that you're putting a pointer to a local variable t into the map. After each loop, t is destroyed and the pointer is no longer valid.
I've no idea why you're using pointers at all, let alone pointers to pointers. You probably want to put the tuples themselves in the map:
std::map<int,std::tuple<int,std::string>> dmap;
for (int i = 0; i<3; ++i){
dmap[i] = {10+i, "test"};
}
i create a while statement in which i assign a pointer to pointer to a map
Sorry for saying this, but it sounds to me like you have bigger problems than the fact that t is the same (this looks like the xy problem).
Consider (in order) one of these alternatives:
store your tuples by value
store your tuples by single pointer (worse than "by value", better than "by pointer to pointer"). If you can do this, consider declaring your map over std::shared_ptr<std::tuple<...>>)
if you really need a map of pointers to pointers to tuples, consider creating a minimal proxy object that acts like a smart pointer to pointer internally (and manages the allocations for you in a safe manner) and like a regular type from the outside (and redeclare your map accordingly).
Either way, if you really need a map of pointers to pointers to tuples (for some reason), the allocation should be done like this:
std::map<int,std::tuple<int,std::string>**> dmap;
int i=0;
while (i<3) {
*dmap[ i ] = new std::tuple<int,std::string>{10 + i, "test"};
++i;
}
(The way you did it added the address of the same local (stack) variable to the map, which would lead to undefined behavior after you exit the local function).
Why are you interested in std::tuple<int,std::string>** ?
Wouldn't a std::tuple<int,std::string>* be sufficient ?
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Well, the address of t is always the same, because it is local variable that is stored on your stack. Each time you enter the block, t will be allocated on the same spot (as you're destroying t after you get out of your while body).
Instead, you need to allocate it on the heap (if this is really what you want to do).
std::tuple<int,std::string>** t = new std::tuple<int,std::string>*();
*t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
I can't see what you're trying to accomplish, but this would be a better solution:
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Even better would be to use smart pointer instead raw one.
Even better would be to store objects by value (no pointers at all).

How to manage an array of pointers to objects?

I have a problem with an array of pointers to objects :(..
I need to generate a dynamic vector of object and then return it in
order to manipulate it in another class. In the code below there is
Event class that is abstract and CarArrival that inherits from it and
can be instantiated.
Inside the class that generate and fill the array I have this function:
Event** EventGenerator::getEvents() {
Event* cars[EVENTS];
for (int i=0; i<EVENTS; i++) {
cars[i] = new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4)));
}
sort(cars, cars+(EVENTS), Event::cmp);
return cars;
}
I invoke this function in onther class in this way:
Event** cars = generator->getEvents();
for(int i=0; i<EVENTS; i++) {
cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
after the print of the first element i get "Segmentation Fault".
I have read some things online and I understand that I mistake since (*cars) evaluates to a
pointer to the first element of the array, in fact I can print the first element and not the other, but I cannot figure out how to access every element of the array in the second class.
How can I face this?
Thanks to all,
Alberto
I'd suggest that you use a std::vector<Event*> instead. You'll save a lot of pain this way. It takes care of all the nasty memory management in the background, and you can easily push any number of items into it. The best part in your case is, that you can simply return a vector which is not safe with a normal array.
Also your Event* cars[EVENTS]; is declared locally in you function. After you have finished it, it ceases to exist, which might cause your Segfault. You'd have to dynamically allocate the array with new, but still, try it with std::vector, see the documentation here.
EDIT: Sample Usage:
std::vector<Event*> EventGenerator::getEvents() {
std::vector<Event*> cars;
for (int i=0; i<EVENTS; i++) {
cars.push_back(new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4))));
}
sort(cars.begin(), cars.end(), Event::cmp);
return cars;
}
std::vector<Event*> cars = generator->getEvents();
for(int i=0; i<cars.size(); i++) {
cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
I believe the cleanest way to handle a dynamic vector of pointers to dynamically allocated objects is to use a boost::ptr_vector. It handles everything you need, including allocation of the space to store the pointers, and deletion of those pointers afterwards.
Wouldn't be better to return vector<Event*> or vector<shared_ptr<Event>> instead of raw pointers? This way you would gain:
Automation of the memory management
Dynamic array with built-in length instead of fixed one
As mentionned by Constantinuis, you are returning the value of a pointer to a memory location that is only valid in the scope of the getEvents() function (it's allocated on the stack). You're bound to get a segfault next time.
You probably want to allocate the memory for this array in the heap (using 'new' if my C++'s isn't too rusty), and then you'll have to deal with freeing the memory later.
http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter13.html