I wrote a dynamically allocated 2D array and for some reason it's not working as I intend it to.
I allocated for a 14x5 array to store values in.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, count, count2;
int size, keysize, column;
size = 7; keysize = 10; column = 5;
int row = (size * keysize) / column; // 14
char **arr = (char **)malloc(column * sizeof(char *));
for(i=0; i<row; i++)
arr[i] = (char *)malloc(row * sizeof(char *));
count=0;
count2=0;
for(i=0; i<keysize; i++)
{
for(j=0; j<size; j++)
{
printf("arr[%d][%d]=", count2, count);
arr[count2][count] = 'C';
printf("%c\n", arr[count2][count]);
count++;
if(count == 5)
{
count = 0;
count2++;
}
}
}
return 0;
}
It seems that the program crashes when a value is to be inserted at the location arr[6][0].
Before that it works fine.
I inserted some printf statements to capture this occurring.
I am not sure why it's doing this, the allocation of memory looks fine with me but I am no expert.
Thanks for any help.
change to
char **arr = (char **)malloc(row * sizeof(char *));
for(i=0; i<row; i++)
arr[i] = (char *)malloc(column * sizeof(char));
I notice the question marked with the c++ tag, the clear way to do this in c++ is to use std::vector. So I'm answering this as if it were a C question:
It looks like you haven't allocated enough space here.
column = 5;
char **arr = (char **)malloc(column * sizeof(char *));
This makes space for 5 pointers to rows. Then later on when you are looping:
for(i=0; i<keysize; i++)//note keysize is 10
{
for(j=0; j<size; j++){ // note size is 7
arr[count2][count];
count++;
if(count == 5){
count = 0;
count2++;//gets incremented every time the inner loop runs
}
}
}
Because count2 gets incremented every time the inner loop runs it will get as big as keysize eventually. That means that arr[keysize][0] must be valid, which it isn't because you in effect made arr[5][14]. The first failure is when you call arr[6][0] which accesses past the end of the array and causes your program to crash.
If the intent here is to initialize variables then to fix this you probably want to loop over the same values for dimensions that you used for allocating the memory.
Related
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.
I am having a problem with passing a char* to an array of char** on my Teensy.
Below is the problematic part:
for (j = 0; j < rulesamountsingle; j++) {
emptybuffer(buff);
char temp[10];
while(!Serial.available());
len = Serial.available();
for (i = 0; i < len; i++) {
temp[i] = Serial.read();
}
temp[len-1] = 0;
fuzzyRulesSingle[j] = temp;
Serial.print(fuzzyRulesSingle[j]);
Serial.print('\n');
}
As you can see, fuzzyRulesSingle[j] (where fuzzyRulesSingle is a char**) will be filled by the variable temp (a char*). As I increment j, the next address in fuzzyRulesSingle will be filled by a new temp.
However, when I print my fuzzyRulesSingle OUTSIDE the code above, all fuzzyRulesSingle will be filled with the last value of temp.
Where have I gone wrong?
You are pointing fuzzyRulesSingle[j] to the temporary char array temp.
A simple way to fix this is to change the fuzzyRulesSingle[j] = temp; to strcpy(fuzzyRulesSingle[j], temp) and changing the declaration of fuzzzyRulessSingle to the size required.
OR
you can declare temp outsize the loop and use malloc to allocate memory necessary and then assign it to fuzzyRulesSingle[j]
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[]/
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.
I have an array of chars. n is array's length
char tab[n];
cin.get(tab, n);
cout<<tab<<"\0"<<endl;
then I create second array
char* t = new char[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab[i];
}
I would like to have pointers to corresponding element. I mean t[2] contains addres of tab[2]. Then I would like to sort array t so tab stays as it was and only t shuffles but when I make change in the array t for example
t[2] = 'a';
I loose t[3]t[4]....
EDIT:
do{
for(int i = 0; i < n -1; i++){
if(t[i] > t[i+1]){
char* x = &t[i];
t[i] = t[i+1];
t[i+1] = *x
}
n--;
}
}while(n>1);
I would like to have pointers to corresponding element. I mean t2 contains addres of tab2.
So try this:
char** t = new (char*)[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab+i; // or `&(tab[i])`
To sort the t array based on tab values, use *t[i] to access character values stored in location i of the t array.
See here and here for good tutorials about C pointers.