c++ malloc and two-dimension array not reserving enough memory - c++

I need to creat a 2 dimension array with malloc, so that I can return it's pointer with a function. In this function I also allocate integers (by getpixel() function) into this array. I do it this way:
int **tab;
tab = (int**)malloc((600) * sizeof(int));
for (int i = 0; i<600; i++)
{
tab[i] = (int*)malloc((800) * sizeof(int*));
}
for (int i = 0; i<600; i++)
{
for (int j = 0; j<800; j++)
{
tab[i][j] = getpixel(i, j);
}
}
This array works of course in most of the cases, when I check it, it has the values I expected inside. However, it stops working, when I get to a bigger Y. So eg. when I want to check array tab[799][599], I can't, because there is an error about exception, I can't copy it directly, because I have the other language than English verion, but it goes something like that:
"The unsupported exception in 0x00E71C05 w bgi.exe: 0xC0000005: violation of rules of access when reading from the location 0x0000095C."
I think it means, that mallock() didn't reserve enought memory for me. But how can I make array big enough then? Or is this any other problem?

Your malloc is wrong, it needs to be like:
int **tab;
tab = (int**)malloc((800) * sizeof(int*));
for (int i = 0; i<800; i++)
{
tab[i] = (int*)malloc((600) * sizeof(int));
}
If you want your array to be 800x600. If you want it to be 600x800 just swap the values.

Related

The array in my singleton isn't keeping information after leaving a function and then it crashes when it tries to access the information again

I have an array called int **grid that is set up in Amazon::initGrid() and is made to be a [16][16] grid with new. I set every array value to 0 and then set [2][2] to 32. Now when I leave initGrid() and come back in getGrid() it has lost its value and is now 0x0000.
I don't know what to try, the solution seems to be really simple, but I'm just not getting it. Somehow the data isn't being kept in g_amazon but I could post the code.
// Returns a pointer to grid
int** Amazon::getGridVal()
{
char buf[100];
sprintf_s(buf, "Hello %d\n", grid[2][2]);
return grid;
}
int Amazon::initGrid()
{
int** grid = 0;
grid = new int* [16];
for (int i = 0; i < 16; i++)
{
grid[i] = new int[16];
for (int j = 0; j < 16; j++)
{
grid[i][j] = 0;
}
}
grid[2][2] = 32;
return 0;
}
int **grid;
g_amazon = Amazon::getInstance();
g_amazon->initGrid();
grid = g_amazon->getGridVal();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
int index;
index = (width * 4 * i) + (4 * j);
int gridval;
gridval = grid[i][j];
lpBits[index] = gridval;
lpBits[index + 1] = gridval;
lpBits[index + 2] = gridval;
}
}
It crashes when I run it at the line where sprintf_s prints out [2][2] and it also crashes when I get to gridval = grid[i][j] because it's at memory location 0x000000.
The variable
int** grid
in the initGrid() function is a local variable. Edit** When the function returns the variable is popped off the stack. However, since it was declared with the new operator the memory still exists on the heap; it is simply just not pointed to by your global grid variable.
#Dean said in comment:
I have grid as an int** grid; in class Amazon {}; so shouldn't it stay in memory or do I need a static var.
That is the problem:
local int **grid; on Amazon::initGrid::
is masking
member int **grid; on Amazon::
as the first context has higher priority in name lookup.
So initGrid() allocates memory referenced only by a local pointer. That pointer no longer exists when you return from this function, Amazon::grid was never touched on initialization and you're also left with some bad memory issues.
So, as commented by #Remy-Lebeau, I also suggest
Consider using std::vector> or std::array, 16> instead. There is no good reason to use new[] manually in this situation.

double free or corruption (out) while deallocating memory in c++

I have a function which returns a 2D array in c++ as follows
float** Input_data(float** train_data, int Nv, int N){
float** x_train=new float*[Nv];
int a = 0,b = 0;
for(a = 1;a<= Nv;a++){
x_train[a] = new float[N+1];
for(b = 1; b <= N+1; b++){
if(b == 1){
x_train[a][b] = 1;
}else{
x_train[a][b] = train_data[a][b-1];
}
}return x_train;}
the purpose of the above code is to add ones in the first column and add remaining data from train_data pointer into x_train. after processing and using x_train i am trying to deallocate x_train as follows
void destroyx_array(float**x_train,int Nv){
for (int free_x = 1;free_x <= Nv;free_x++){
delete[] x_train[free_x];}delete[] x_train;}
and calling the destroy function as follows
destroyx_array(x_train,Nv)
the Input_data functions works fine but when i try to destroy_x_array it gives me double free or corruption(out) aborted (core dumped) can anybody explain what wrong i am doing ? thank you
Simply put, your code corrupts memory. The best thing is to not use raw pointers and instead use container classes such as std::vector.
Having said that, to fix your current code, the issue is that you're writing beyond the bounds of the memory here:
for(a = 1;a<= Nv;a++)
when a == Nv, you are writing one "row" beyond what was allocated. This looks like a manifestation of attempting to fake 1-based arrays. Arrays in C++ start from 0, not 1. Trying to fake 1-based arrays invariably can lead to bugs and memory corruption.
The fix is to rewrite your function to start from 0, not 1, and ensure your loop iterates to n-1, where n is the total number of rows:
for (a = 0; a < Nv; ++a)
the purpose of the above code is to add ones in the first column and
add remaining data from train_data pointer into x_train
Instead of the loop you wrote to test for the first column, you could simplify this by simply using memcpy:
for (int i = 0; i < Nv; ++i)
{
x_train[i][0] = 1;
memcpy(&x_train[i][1], &train_data[i][0], N * sizeof(float));
}
Thus the entire function would look like this:
float** Input_data(float** train_data, int Nv, int N)
{
float** x_train=new float*[Nv];
for(int a = 0; a < Nv; a++)
x_train[a] = new float[N+1];
for (int a = 0; a < Nv; a++)
{
x_train[i][0] = 1;
memcpy(&x_train[i][1], &train_data[i][0], N * sizeof(float));
}
return x_train;
}

How to insert an object in the array of pointers

I have an array of pointers:
Hotel *hotels[size];
for (int i = 0; i < size; ++i)
hotels[i] = new Hotel();
And I want to insert an object in this array after some object with name I know:
cin >> tmp_name;
for (int i = 0; i < size; i++) {
if (hotels[i]->get_name() == tmp_name) {
hotels[size] = new Hotel();
size += 1;
Hotel *tmp_hotel;
tmp_hotel = hotels[i+1];
hotels[i+1]->fillHotel();
for (i = i + 2; i < size; i++) {
hotels[i] = tmp_hotel;
tmp_hotel = hotels[i+1];
}
break;
}
}
What I do wrong?
UPD:
My solution:
cin >> tmp_name;
for (int i = 0, j = 0; i < size; i++, j++) {
new_hotels[j] = hotels[i];
if (hotels[i]->get_name() == tmp_name) {
new_hotels[j+1]->fillHotel();
++j;
system("clear");
}
}
hotels[size] = new Hotel();
++size;
for (int i = 0; i < size; i++) {
hotels[i] = new_hotels[i];
}
I can see different errors in your code.
For example:
Hotel *hotels[size];
size should be a constant expression and something let me think this is not the case. VLA are not part of the C++ standard. In short you cannot allocate dynamic memory on the stack. The proper initialization should be:
Hotel* hotels = new Hotel*[size];
The line in the loop:
hotels[size] = new Hotel();
you're actually accessing out of bounds of your array: size index is some memory is not included in your array and this will produce an undefined behaviour.
Another strange line is the following:
size += 1;
Despite the fact that confirms size is not a constant, you cannot increase your size of vector simply changing that variable. You're actually just changing a variable size, but the allocated memory for your array will be the same.
How resolve?
In order in increase (or change) the size of an array, the solution is almost always to create a new array, copy the old one. In your case that solution is pretty reasonable because you should copy just pointers and not entire objects.
There are a lots of question on S.O. where this topic is, for example here.
Despite of that, I strongly suggest you to use the most practical alternative, that is to use a real C++ code.
The most efficient class is std::vector which is a C++ way to handle dynamic array.
Finally, you should also consider the std::unique_ptr<T> class to handle dynamic memory and pointers.
The final solution will be a class:
std::vector<std::unique_ptr<Hotel>> hotels;

Function behaves badly when passing dynamically allocated pointer

I have this function
void shuffle_array(int* array, const int size){
/* given an array of size size, this is going to randomly
* attribute a number from 0 to size-1 to each of the
* array's elements; the numbers don't repeat */
int i, j, r;
bool in_list;
for(i = 0; i < size; i++){
in_list = 0;
r = mt_lrand() % size; // my RNG function
for(j = 0; j < size; j++)
if(array[j] == r){
in_list = 1;
break;
}
if(!in_list)
array[i] = r;
else
i--;
}
}
When I call this function from
int array[FIXED_SIZE];
shuffle_array(array, FIXED_SIZE);
everything goes all right and I can check the shuffling was according to expected, in a reasonable amount of time -- after all, it's not that big of an array (< 1000 elements).
However, when I call the function from
int *array = new int[dynamic_size];
shuffle_array(array, dynamic_size);
[...]
delete array;
the function loops forever for no apparent reason. I have checked it with debugging tools, and I can't say tell where the failure would be (in part due to my algorithm's reliance on random numbers).
The thing is, it doesn't work... I have tried passing the array as int*& array, I have tried using std::vector<int>&, I have tried to use random_shuffle (but the result for the big project didn't please me).
Why does this behavior happen, and what can I do to solve it?
Your issue is that array is uninitialized in your first example. If you are using Visual Studio debug mode, Each entry in array will be set to all 0xCC (for "created"). This is masking your actual problem (see below).
When you use new int[dynamic_size] the array is initialized to zeros. This then causes your actual bug.
Your actual bug is that you are trying to add a new item only when your array doesn't already contain that item and you are looking through the entire array each time, however if your last element of your array is a valid value already (like 0), your loop will never terminate as it always finds 0 in the array and has already used up all of the other numbers.
To fix this, change your algorithm to only look at the values that you have put in to the array (i.e. up to i).
Change
for(j = 0; j < size; j++)
to
for(j = 0; j < i; j++)
I am going to guess that the problem lies with the way the array is initialized and the line:
r = mt_lrand() % size; // my RNG function
If the dynamically allocated array has been initialized to 0 for some reason, your code will always get stack when filling up the last number of the array.
I can think of the following two ways to overcome that:
You make sure that you initialize array with numbers greater than or equal to size.
int *array = new int[dynamic_size];
for ( int i = 0; i < dynnamic_size; ++i )
array[i] = size;
shuffle_array(array, dynamic_size);
You can allows the random numbers to be between 1 and size instead of between 0 and size-1 in the loop. As a second step, you can subtract 1 from each element of the array.
void shuffle_array(int* array, const int size){
int i, j, r;
bool in_list;
for(i = 0; i < size; i++){
in_list = 0;
// Make r to be betwen 1 and size
r = rand() % size + 1;
for(j = 0; j < size; j++)
if(array[j] == r){
in_list = 1;
break;
}
if(!in_list)
{
array[i] = r;
}
else
i--;
}
// Now decrement the elements of array by 1.
for(i = 0; i < size; i++){
--array[i];
// Debugging output
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
}
You are mixing C code with C++ memory allocation routines of new and delete. Instead stick to pure C and use malloc/free directly.
int *array = malloc(dynamic_size * sizeof(int));
shuffle_array(array, dynamic_size);
[...]
free(array);
On a side note, if you are allocating an array using the new[] operator in C++, use the equivalent delete[] operator to properly free up the memory. Read more here - http://www.cplusplus.com/reference/new/operator%20new[]/

Two-dimensional array initialization

CASE1:
int nrows=5;
int ncols=10;
int **rowptr;
rowptr=new int*;
for(int rows=0;rows<nrows;rows++) {
for(int cols=0;cols<ncols;cols++) {
*rowptr=new int;
}
}
CASE2:
int nrows=5;
int ncols=10;
int **rowptr;
for(int rows=0;rows<nrows;rows++) {
rowptr=new int*;
for(int cols=0;cols<ncols;cols++) {
*rowptr=new int;
}
}
I am able to insert and print values using both ways. What is the difference in initializations?
What is the difference?
#1 just allocates memory enough to hold a integer pointer and not an array of integer pointers.
#2 Causes a memory leak by just overwritting the memory allocation of the previous iteration.
I am able to insert and print values using both the ways
Memory leaks and Undefined behaviors may not produce immediate observale erroneous results in your program but they sure are good cases of the Murphy's Law.
The correct way to do this is:
int nrows = 5;
int ncols = 10;
//Allocate enough memory for an array of integer pointers
int **rowptr = new int*[nrows];
//loop through the array and create the second dimension
for (int i = 0;i < nrows;i++)
rowptr[i] = new int[ncols];
You have a memory leak in both cases.
The proper way to initialize such a "2d" array is
int** arr = new int*[nrows];
for (int i = 0; i < nrows; i++)
arr[i] = new int[ncols];
Note however, that it isn't a 2d array as defined by C/C++. It may not, and probably will not, be consecutive in memory. Also, the assembly code for accessing members is different.
In your case, the accessing by indexing is equivalent to *(*(arr+i)+j)
And in the case of a 2d array it's *(arr + N_COLS*i + j) when N_COLS is a compile time constant.
If you want a true 2d array you should do something like this:
int (*arr)[N_COLS] = (int(*)[N_COLS])(new int[N_ROWS * N_COLS])
You'd better use 1d array to manage 2d array
int **x = new int*[nrows];
x[0] = new int[nrows*ncols];
for (int i = 1; i < nrows; i++)
x[i] = x[i-1] + ncols;
for (int i = 0; i < nrows; i++)
for (int j = 0; j < ncols; j++)
x[i][j] = 0;
delete [] x[0];
delete [] x;