My program doesn't execute because of an static value - c++

I have this chunk of a program that merges two arrays in one. The matter is that I got this message once the program is compiled:
main.cpp:20:21: error: storage size of ‘cont’ isn’t known
Why does it happen?
Leave my code below:
int * merge(int *array_1, int *array_2, int n1, int n2)
{
static int cont[n1 + n2];
int i = 0, j = 0, k = 0;
while(i < n1 && j < n2)
if(array_1[i] < array_2[j])
cont[ k++ ] = array_1[ i++ ];
else
cont[ k++ ] = array_2[ j++ ];
if(i == n1)
for(int index = j; index < n2; index++)
cont[ k++ ] = array_2[ index ];
else if(j == n2)
for(int index = i; index < n1; index++)
cont[ k++ ] = array_1[ index ];
for(int i = 0; i < k; i++)
printf("%d ", cont[i]);
return cont;
}

In C++ a static array needs to have a size which is known during compile time. If you do not know the size beforehand it is by default a dynamic array independently if it residing on the stack: int my_array[n] or on the heap: int* my_array = new int[n] (The latter is strictly speaking not an array but behaves similar)
So essentially if you want to dynamically create the array you need to drop the static. However given how it is used in your example it will either way not work, because you return the address of a local variable which will be destructed when leaving the scope. Essentially your return value will point into no-mans-lands.
I would suggest to use std::vector instead. Please note that I also adjusted the insert logic and made it a bit easier to read because I had trouble to figure out which order your wanted to achieve when going through your example. Now it is ordered the following way:
values from array1 and and array2 are inserted alternating.
If one array is longer than the other those values are added in the end.
#include <vector>
std::vector<int> merge(int *array_1, int *array_2, int n1, int n2)
{
std::vector<int> v;
int shorter_length = n1 < n2 ? n1 : n2;
for (int i = 0; i < shorter_length; i++) {
v.push_back(array_1[i]);
v.push_back(array_2[i]);
}
for (int j = shorter_length; j < n1; ++j) {
v.push_back(array_1[j]);
}
for (int j = shorter_length; j < n2; ++j) {
v.push_back(array_2[j]);
}
for(auto& element : v)
printf("%d ", element);
return v;
}
You can play around with this example: https://godbolt.org/z/fT6xzo

the initialized static variable will be put in the "data" segment, so the compiler should know how much space should be allocated for it in the executable file.
the uninitialized static variable will be put the "bss" segment, although there will no exactly size of space left for it in the executable file (because data in "bss" segment is all zero, so the compiler can just leave a start address and a size is enough. when the executable file be loaded into memory, the loader will allocate real memory for the "bss" segment according to the start address and the size). the compiler should also know the size of the variable too, only in this way, the compiler can 'tell' this size to loader, so that the loader can know how much memory should be allocated for the "bss" segment when loading the executable into memory.

Related

Memory allocation with looping in C++

I have a List class for char arrays. And I want to push back N arrays from 'a' to 'a..a'.
char* x;
SList list;
for (unsigned int i = 1; i < n+1; i++) {
x = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[j] = 'a';
}
x[i] = '\0';
list.push_back(&x);
}
But every time, x has the same address. And in result, my List object contains N pointers to the same address.
Is there a way to push back these arrays in loop with correct memory allocation?
Before asking found this question, but it doesn't provide a cool solution for my problem.
In each iteration of the loop x = new char[i+1]; returns a different address, which is stored in x. So the value of x changes in each iteration, yet, the address of x doesn't.
Did you mean
list.push_back(x);
to add the address of the newly allocated memory? Of course this would require you to change the type of list the a collection of char *.
It must be mentioned that dereferencing &x after x goes out of scope will lead to undefined behaviour, because x doesn't exist anymore. You fill list with dangling pointers.
Finally I'd like to mention that you could avoid the nasty manual memory management and simply use a std::vector<std::string>.
std::vector<std::string> list;
for (unsigned int i = 1; i < n+1; i++) {
std::string newString(i, 'a'); // string with i times 'a'
list.push_back(newString);
}
Ok. I found a pretty straightforward solution:
char** x = new char*[n];
SList sl;
for (unsigned int i = 0; i < n; i++) {
x[i] = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[i][j] = 'a';
}
x[i][i] = '\0';
sl.push_back(&x[i]);
}
With having N addresses to store pointers to arrays. I can just add their addresses to my list object

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.

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[]/

C/C++ How a 3 dimensional array is stored in memory and what is the fastest way to traverse it

I am trying to understand how a 3 dimensional array is stored in memory and the difference between how std:vector is stored.
This is the way I understand that they are stored, and std::vectors, same way, with the difference that they make full use of memory blocks
a[0][0][0] a[0][0][1] a[0][0][2]... a[0][1][0] a[0][1][1] ... a[1][0][0] a[1][0][1]...
My goal is to find which is the most efficient way to traverse and array.
For example, I have array:
v[1000][500][3];
so how is more efficient to traverse it?
for(i = 0; i < 1000; i++)
{
for(j = 0; j < 500; j++)
{
for(k = 0; k < 3; ++k)
{
//some operation
}
}
}
or may be it would be more efficient to declare the array as;
v[3][500][1000]
and to traverse as
for(i = 0; i < 3; i++) {
for(j = 0; j < 500; j++)
{
for(k = 0; k < 1000; ++k)
{
//some operation
}
} }
Is there any CL tool to visualize how arrays are stored?
You're right in your representation of arrays in memory values are contiguous. So an int v[2][2][2] initialized to 0 would look like:
[[[0, 0], [0, 0]], [[0, 0], [0, 0]]]
As far as performance goes you want to access data as close to each other as possible to avoid data cache misses so iterating on the outer most dimension first is a good thing since they are located next to each other.
Something that might happen though with your first example is the compiler might optimize the inner loop(if right conditions are met) and unroll it so you would save some time there by skipping branching.
Since both your example are already iterating in the right way, I would say profile it and see which is faster.
std::vector also store its element contiguous in memory but since it is 1 dimension, locality apply by default(provided you aren't iterating randomly). The good side of vector is they can grow whereas an array can't(automatically anyway).
When the memory address is continuous (e.g., complied time array a[][][]), the most efficient way to traverse a multidimensional array is use a pointer. The a[i][j][k] actually is &a[0][0][0]+(i*j*k + j*k + k). Thus, initialize a pointer p to the beginning address, then calls *(p++)
int main() {
int a[2][3]={{1,2,3},{4,5,6}};
int *p = &a[0][0];
for( int i=0; i<6; ++i ){
cout<<*(p++)<<endl;
}
return 0;
}
To make it visible:
#include <iostream>
int main()
{
int a[][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
int* p = reinterpret_cast<int*>(a);
for(unsigned i = 0; i < 6; ++i) {
std::cout << *(p + i);
}
std::cout << std::endl;
return 0;
}
Shows a row major order - see: http://en.wikipedia.org/wiki/Row-major_order
Having this, you should iterate per row to utilize the cache. In higher dimension N you will get similar, where each element represents a block of data with a dimension N-1

Filling an array with integers

I'm trying to fill an array with numbers 1111 to 8888, with each integer in the number being between 1 and 8 in c++. However, when I run it, it's only outputting large negative numbers indicating an error. I honestly have clue what the error is so it would be appreciated if you could help me out. Thanks!
int fillArray()
{
int arrayPosition;
int guesses[4096];
arrayPosition = 0;
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses[arrayPosition] = ((i * 1000) + (j * 100) + (k *10) + m);
cout << guesses[arrayPosition];
arrayPosition++;
}
return guesses[4096];
}
Your return type is wrong. int fillArray(), but you're trying to return an int[4096] that was declared on the stack... What you're actually doing with return guesses[4096]; is returning the first memory location after your array in memory, which is probably just garbage, hence your issue with large negative numbers.
You can fix it by allocating your array in the heap, and returning a pointer to the start of that array:
int * fillArray()
{
int arrayPosition;
int * guesses = new int[4096];
// other stuff stays the same...
return guesses;
}
However, since your function is called fillArray, it would make more sense to pass in an array and fill it rather than creating the array in the function. (If you wanted to do that, might call it something like make_1_to_8_array instead, to make it more clear that you're constructing something that will need to be deleted later.) Giving an int* as the first argument would allow you to pass in the base address of your array that you want filled:
void fillArray(int * guesses)
{
int arrayPosition;
// other stuff stays the same...
}
Or, if you want to verify that the you're using an array of the exact size:
void fillArray(int (&guesses)[4096])
{
int arrayPosition;
// other stuff stays the same...
}
Note that the function now returns void since you just update the array that was passed in, and you don't need to return anything new.
Your for-loops look correct, but your array handling is off, as is highlighted by other answers.
It is more usual in C++ to use std::vector and to pass this in by reference as an argument. This saves you having to handle memory allocations and deallocations. Here's an example, including the output in the for-loops:
#include <iostream>
#include <vector>
int fillArray(std::vector<int>& guesses)
{
for (int i = 1; i <= 8; i++)
for (int j = 1; j <= 8; j++)
for (int k = 1; k <= 8; k++)
for (int m = 1; m <= 8; m++)
{
guesses.push_back((i * 1000) + (j * 100) + (k * 10) + m);
std::cout << guesses.back() << std::endl;
}
return guesses.back();
}
int main()
{
std::vector<int> guesses;
std::cout << fillArray(guesses) << std::endl;
}
You are creating your array locally then attempting to return it. If you try printing (to debug) out the result of your array prior to returning, you will see it is ok. However, once you return, the array is no linger valid. Try passing in an array into your function instead.