Failed to allocate an array of pointers to a struct - c++

I'm trying to allocate an array of pointers to a struct but there's something wrong with my code.
This is my struct:
struct Brick {
GameObject2D* handle_;
};
Brick** bricks_;
And this is how i'm trying to allocate memory for it:
int bricks_amount_ = 10;
bricks_ = (Brick**)malloc(sizeof(Brick*) * bricks_amount_);
The program crash. I've make a devenv on it to debug where's the problem and it crash on this line:
for (unsigned short int i = 0; i < bricks_amount_; i++){
bricks_[i]->handle_ = new GameObject2D(); <---------- CRASH!
}
Any suggestions?
PS: Sorry for my english :P
=========================================================================
[SOLUTION]
Finally i've decided to use std::vector instead raw pointers:
bricks_.resize(bricks_amount_);
but i've tried to make the malloc different way and it works too:
bricks_ = (struct Brick*)malloc(sizeof(struct Brick) * bricks_amount_);
or this:
bricks_ = new Brick[bricks_amount_];
Thank you to the people who wants to help!

It's C++:
don't use malloc, use new
don't use plain arrays, use std::vector or std::array
don't use raw pointers, use std::unique_ptr

Do not use
Bricks ** //will be a 2 dimensional array
Use instead
Bricks * //will be a 1 dimensioanal array
If you want a single dimensional array
Then do
`Bricks * bricks_ = (Bricks *)malloc(sizeof(Brick) * bricks_amount_ );
`
Then you can safely do without a crash
for (unsigned short int i = 0; i < bricks_amount_; i++){
bricks_[i]->handle_ = new GameObject2D(); <---------- There will not be CRASH!
}

Related

c++ : An array of the pointer float type with dynamic size

Is this Correct?
Will stereoBuffer be an array of the pointer float type with size mixQty (i.e. 2);
// C++ in Header File
float **stereoBuffer;
// in cpp file inside a function of init
mixQty = 2; // this will be passed in function
stereoBuffer = new float*[mixQty];
for (int i = 0; i < mixQty; ++i) {
stereoBuffer[i] = (float *)malloc(samplerate * 2 * sizeof(float) + 32768);
}
Help and Detail answer will be rewarded.
Is this Correct?
No. Mixing new and malloc() is not a good idea.
If you must use dynamic memory allocation, then read this: How do I declare a 2d array in C++ using new?
Otherwise, use an std::vector.
Will stereoBuffer be an array of the pointer float type
It will be (a pointer to the first element of) an array of type pointer-to-float.
Each element of this array will be a pointer to the first element of an array of float.
As gsamaras notes, mixing new and malloc like this is terrible practice. It's needlessly hard to correctly deallocate and there's no error checking. You could at least use std::vector<std::unique_ptr<float[]>> and let it take care of deallocation correctly for you.
using StereoBuffer = std::vector<std::unique_ptr<float[]>>;
StereoBuffer allocateStereoBuffer(size_t mixQty, size_t samplerate)
{
StereoBuffer buf(mixQty);
for (size_t i = 0; i < mixQty; ++i) {
buf[i] = make_unique<float[]>(samplerate * 2 * 32768); // ?
}
return buf;
}

C++ error on delete[] after iterating through pointer

Environment: Windows 7 pro x64, Microsoft Visual Studio 2015 Enterprise, Version 14.0.25424.00 Update 3
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
std::string _orig2 = "[999 99% (1/1)O:999]";
char *orig = NULL;
char *orig2 = NULL;
orig = new char[_orig.length() + 1];
strcpy(orig, _orig.c_str());
orig2 = new char[_orig2.length() + 1];
strcpy(orig2, _orig2.c_str());
*orig++;
*orig2++;
int a = atoi(orig);
int b = atoi(orig2);
delete[] orig;
delete[] orig2;
return 0;
}
Running the above code crashes with the "_CrtIsValidHeapPointer(block)" error.
If I don't iterate (*orig++ and *orig2++), then no issues.
So my question is, how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
You did not delete the pointers you allocated!
delete must be called on the original memory address returned by new. Since you did orig++, you cant delete the address being pointed at!
Iterating can be done with an index, and using array subscription to dereference:
orig[i] = 'a';
Which is the same as doing this:
*(orig+i) = 'a';
Or you can get another pointer onto the same data, and modify this one.
char* pOrig = orig;
++pOrig;
Why did you write
*orig++; // why dereferencing?
Just ++ by itself would do the iteration.
Avoid to use raw pointers. Your code can be simpler:
std::string orig = "[188 80% (1/2)O:152]";
std::string orig2 = "[999 99% (1/1)O:999]";
int a = atoi(orig.c_str() + 1);
int b = atoi(orig2.c_str() + 1);
Your mistake is that you try to delete the shifted pointers instead of the original pointers. As the result heap manager gets wrong allocated block information usually put before the allocated pointer and you got heap corruption.
how can I iterate through the pointers and then when I'm done doing what I need to do with them, delete[] them correctly?
Create a copy of the pointer:
char* orig = new char[size];
char* i = orig;
*i++ = 'a';
delete orig;
A perhaps more common idiom is to dereference a temporary:
for(int i = 0; i < size - 1; i++)
orig[i] = 'a';
I would love to [use std::string], but I need to use atoi(), which won't work on std::string
You are mistaken. atoi works with std::string just fine. Simply use std::string::c_str() just like you did with strcpy. There is absolutely no reason to allocate a block of memory with new.
int testFunction()
{
std::string _orig = "[188 80% (1/2)O:152]";
int a = 0;
for (std::string::iterator it = _orig.begin(); it != _orig.end(); ++it)
{
if (isdigit((char)*it))
a = (atoi(it._Ptr));
}
return 0;
}
I got it. Thanks for everyone who helped me come to this conclusion. Staying with std::string was in fact the best approach.

Reallocating 2D arrays on C++

lets say i have:
#include <iostream>
using namespace std;
int **a; //Global Variable
int main()
{
n=5;
a = new int*[n];
for ( int i = 0 ; i < n ; i++ )
a[i] = new int[n] ;
}
is there any realloc() method to increase the row size? (column size is fixed)
I mean if the row size is 5 then i wanna make it 6 not much more, just +1.
I use
for(i=0;i<n;i++)
{
counter++;
a[i] = (int *) realloc(a[i],counter*sizeof(int));
}
but i think something is wrong....
Edit: please don't advise any vector or sth like that.. Cuz i need my array as global.
realloc only works when you allocated with malloc. If you used new, you'll have to delete and then use new again (or just use something like a std::vector).
EDIT: Since you asked for an example of how to use malloc:
a = new int*[n];
would become
a = (int **) malloc (n * sizeof (int *));
and
a[i] = new int[n] ;
would become
a[i] = (int *) malloc (n * sizeof (int));
You can write your own routine to resize the array.
If you want a resized block with size N
allocate (new) the new size N
copy old array/block to this newly allocated array/block
free the old array (delete)
To avoid calling this routine again and again, better preallocate a large chunk, the size of chunk will be determined by the need of your application, and should be such which avoid resizing the array a lot of times.
The answer is No!
C++ memory management does not contain functionality for reallocating/resizing allocated memory. You would have to implement such a thing yourself using new/copy/delete semantics

Dynamically Changing the Size of the Pointer in C++

I have the following structure
typedef struct DeviceInfo
{
char[30] name;
char[30] serial Number;
}DeviceInfo;
I am doing this
DeviceInfo* m_DeviceInfo = new DeviceInfo[4];
// Populate m_DeviceInfo
Then I wanted to re size m_DeviceInfo to 6 and want to preserve the
Previous 4 Value as well.
How to do it in c++ ?
You can't do that with regular arrays. I suggest you to use vector which is able to grow as you add more elements to it (so you don't even have to specify initial size).
The good C++ way is to use an appropriate container for that. Apparently, you should use the std::vector container, e.g:
std::vector<DeviceInfo> m_DeviceInfo;
m_DeviceInfo.resize(4);
This requires some constraints on your DeviceInfo. In particular, it should have a constructor without arguments, and copy constructors...
And your question is badly phrased. You certainly don't change sizeof(DeviceInfo*) which is probably 4 bytes on a 32 bits machine, and 8 bytes on a 64 bits one.
m_DeviceInfo points to an array of DeviceInfo of 4 elements. There is no resizing with arrays. Instead you should delete and create it with 6 elements.
DeviceInfo * m_DeviceInfo2 = new DeviceInfo[6];
memcopy( m_DeviceInfo,m_DeviceInfo2, 4 );
delete[] m_DeviceInfo;
But you should use a vector.
std::vector<DeviceInfo> m_DeviceInfo;
// or
std::vector<std::shared_ptr<DeviceInfo>> m_DeviceInfo;
To resize it
m_DeviceInfo.resize(m_DeviceInfo.size()+ 2);
You have two options in your problem and it depends if you want to use STL or not.
typedef struct DeviceInfo
{
char[30] name;
char[30] serial Number;
} DeviceInfo;
With STL:
//requires vector.h
vector<DeviceInfo> m_deviceInfo;
DeviceInfo dummy;
dummy.name = "dummyName";
dummy.serialNumber = "1234";
m_deviceInfo.insert(m_deviceInfo.begin(), dummy);
//add as many DeviceInfo instance you need the same way
or without STL:
//implement this
DeviceInfo* reallocArray(DeviceInfo* arr, int curItemNum, int newItemNumber)
{
DeviceInfo* buf = new DeviceInfo[newItemNumber];
for(int i = 0; i < curItemNum; i++)
buf[i] = arr[i];
for(int i = curItemNum; i < newItemNumber; i++)
buf[i] = null;
}
//and in your main code
DeviceInfo m_DeviceInfo = new DeviceInfo[4];
m_DeviceInfo = reallocArray( m_DeviceInfo, 4, 6 );
1) Make a new array of size that fits, and copy all elements of the old array to the new one.
2) Use the std::vector (my recommendation).
The best possible solution is using vector in your program.
Refer this site http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html#VECTOR
This site will help you to solve your problem.
Here you can push the data.No need to bother about the size of structure.
Your syntax is wrong:
DeviceInfo m_DeviceInfo = new DeviceInfo[4];
should be:
DeviceInfo* m_DeviceInfo = new DeviceInfo[4];
A better alternative would be the use of std::vector.
std::vector<DeviceInfo> vec;
//populate:
DeviceInfo inf;
vec.push_back(inf);
vec.push_back(inf);
//....
well there are several ways to do this, but
you should use the realloc function in c++. it will reallocate contiguous memory and also copies the value of previous memory into the new ones. for example:
temp_DevInfo = (DeviceInfo*) realloc (m_DeviceInfo, (2) * sizeof(struct DeviceInfo));
free(m_DeviceInfo);
m_deviceInfo = temp_DevInfo;
you do 2 * sizeof(DeviceInfo) because you want to add 2 more, plus the previous 4 is 6.
then you should free/delete the previous object.
and finally set old pointer to point to the new object you just allocated.
that should be the gist of it
look at the documentation of realloc.

2d boolean array initialization in c++

I don't use C that much and I recently got confused about 2d array initialization problem. I need to debug somebody's code and stuck in the following(her original code):
const int location_num = 10000;
bool **location_matrix;
if (node_locations)
{
location_matrix = (bool **)malloc(location_num*sizeof(bool *));
if (!location_matrix)
{
cout<<"error 1 allocating location_matrix" << endl;
exit;
}
for (i=0; i<location_num; i++)
{
location_matrix[i] = (bool *) malloc(location_num*sizeof(bool ));
if (!location_matrix[i])
{
cout<<"error 2 allocating location_matrix" << endl;
exit;
}
for (j=0; j<location_num; j++)
location_matrix[i][j] = false;
}
}
I thought is was redundant, so I changed it to the following:
location_matrix[location_num][location_num] = { {false} };
However, segmentation fault happens at runtime.
My question is: how does the above code fail? If it looks right, what's the difference between dynamically allocation and static allocation? Is it just because the dimension might not be constant, so we need to do it dynamically?
Also, just for curiosity, how do I malloc 2d array that stores pointers? Thanks.
The change would likely require about 100MB (10,000 * 10,000 * 1) on the stack, so the segmentation fault was likely due to a stack overflow.
Edit I originally stated 400MB in the answer, but #Mooing Duck points out bool will likely be 1 byte. I was thinking the Win32 BOOL (for no real reason at all), which is typedefed to an int.
I actually don't see anything wrong with the code.
The following code doesn't work because location_matrix is not allocated:
location_matrix[location_num][location_num] = { {false} };
GCC will allow the following (as an extension):
bool location_matrix[location_num][location_num] = { {false} };
But it will blow your stack because 10000 x 10000 is too large.
Currently, your code uses dynamic allocation. That's the correct way to do it because the matrix is too large to be done as a static array (and may overrun the stack).
As for your last question, "how to make a 2d array that stores pointers": It can be done almost the same way as your current code. Just change bool to int*.
So a 2D array of NULL int pointers will look like this:
int ***location_matrix;
if (node_locations)
{
location_matrix = (int***)malloc(location_num*sizeof(int**));
if (!location_matrix)
{
cout<<"error 1 allocating location_matrix" << endl;
exit;
}
for (i=0; i<location_num; i++)
{
location_matrix[i] = (int**) malloc(location_num*sizeof(int*));
if (!location_matrix[i])
{
cout<<"error 2 allocating location_matrix" << endl;
exit;
}
for (j=0; j<location_num; j++)
location_matrix[i][j] = NULL;
}
}
The standard library is your friend.
#include <vector>
int
main()
{
int location_num = 1000;
std::vector<std::vector<bool> > location_matrix(location_num, std::vector<bool>(location_num, false));
}
Second, the array is likely too large to fit on the stack, so you'd need to dynamically allocate it -- but you can simplify the code as long as the difference between a 2-dimensional array and an array of pointers won't be an issue (as it would be if you needed to pass the array to a function or use pointer arithmetic with it).
You could use something like this:
bool (*location_matrix)[location_num];
location_matrix = (bool (*)[location_num])calloc( location_num,
location_num * sizeof(bool) );
...which allocates space for the whole two-dimensional array and gives a pointer to an array of bool arrays with location_num elements each.