I have a structure , which present my element of data
struct myElement
{
int field1;
int field2;
int field3;
};
another structure, which contain array of this elements and some another data
struct myArray
{
struct myElement *elements;
int someData;
};
and I need to have array of this arrays like that
struct myArray *myMatrix;
But I have a problem with memory allocation. Count of elements in myArray's can be different, in myMatrix too, so I need to allocate memory dynamicaly. What is the corret way to allocate and deallocate memory in this situation?
Here's a small example of how you would allocate (malloc) and deallocate (free) a dynamic struct myElement array in a struct myArray. Note also that you will need to keep track of the size of the array, so I added size_t elements_len; to struct myArray (excuse the combination of camelCase and underscores - I use underscores in C, but didn't want to modify your identifiers):
#include <stdlib.h>
struct myElement
{
int field1;
int field2;
int field3;
};
struct myArray
{
struct myElement *elements;
size_t elements_len;
int someData;
};
void allocate_elements(struct myArray *m, size_t length)
{
m->elements = malloc(length * sizeof( *m->elements) );
m->elements_len = length;
}
void free_elements(struct myArray *m)
{
free(m->elements);
m->elements = NULL; /* point to NULL to signify no array allocated */
m->elements_len = 0; /* length of 0 also signifies no elements/no array */
}
int main(void)
{
struct myArray ma;
allocate_elements(&ma, 5);
free_elements(&ma);
return 0;
}
Apply similar logic in order to have a dynamic array of struct myArray. You would malloc enough memory for X amount of struct myArrays, then for each struct myArray element in that array, you would call allocate_elements. Then iterate through each element in the array once you're done with it and call free_elements.
Use malloc to allocate the memory:
myMatrix = malloc(sizeof(myArray)*dim1);
for (int i = 0; i < dim1; i++)
myMatrix[i].elements = malloc(sizeof(myElement)*dim2);
Use free in similar fashion to release the memory once you're done with it.
struct myArray *myMatrix = malloc(Nentries * sizeof(*myMatrix));
if (myMatrix != 0)
{
for (int i = 0; i < Nentries; i++)
{
myMatrix[i].elements = malloc(Nelements[i] * sizeof(myElement));
if (myMatrix[i].elements != 0)
{
for (int j = 0; j < Nelements[i]; j++)
{
myElement *e = &myMatrix[i].elements[j];
e->field1 = 0;
e->field2 = 1;
e->field3 = 2;
}
myMatrix[i].someData = 37;
}
}
}
I'm assuming that Nentries says how many elements there are in the matrix, and that each element of the array Nelements indicates how many elements are in the corresponding element of the matrix. The code tests for successful memory allocation, but does not react to allocation failure.
int num_elements = 1234; // whatever
struct myArray *myMatrix;
myMatrix = malloc (num_elements * sizeof (*myMatrix));
if (!myMatrix)
// error
// subsequent use of myMatrix is just like it had been statically dimensioned:
myMatrix [0].someData = 343;
myMatrix [1].someData = 323;
You need to use malloc and free functions to dynamically allocate and free the memory. Please use the following as a reference.
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct myElement {
int field1;
int field2;
int field3;
};
struct myArray {
struct myElement *elements;
int someData;
};
struct myArray *myMatrix = NULL;
int n_myarray = 0;
int n_elements = 0;
int i, j;
printf("How many myArray's do you want? ");
scanf("%d", &n_myarray);
printf("How many elements do you want in each array? ");
scanf("%d", &n_elements);
/* memory allocation starts here */
if ((myMatrix = (struct myArray *) malloc((int)sizeof(struct myArray) * n_myarray)) == NULL) {
printf("ERROR: unable to allocate array\n");
return 1;
}
for (i=0 ; i<n_myarray ; i++) {
if ((myMatrix[i].elements = (struct myElement *) malloc((int)sizeof(struct myElement) * n_elements)) == NULL) {
printf("ERROR: unable to allocate array elements\n");
free(myMatrix);
return 1;
}
/* initialization of other members of struct myArray goes here */
myMatrix[i].someData = 123;
/* initialization of members of struct myElement goes here */
for (j=0 ; j<n_elements ; j++) {
myMatrix[i].elements[j].field1 = 123;
myMatrix[i].elements[j].field2 = 123;
myMatrix[i].elements[j].field3 = 123;
}
}
/* do your calculations here */
/* I'm printing the values */
for (i=0 ; i<n_myarray ; i++) {
printf("myMatrix[%d].someData : %d \n", i, myMatrix[i].someData);
for (j=0 ; j<n_elements ; j++) {
printf("myMatrix[%d].elements[%d].field1 : %d \n", i, j, myMatrix[i].elements[j].field1);
printf("myMatrix[%d].elements[%d].field2 : %d \n", i, j, myMatrix[i].elements[j].field2);
printf("myMatrix[%d].elements[%d].field3 : %d \n", i, j, myMatrix[i].elements[j].field3);
}
}
/* memory deallocation (free) starts here */
for (i=0 ; i<n_myarray ; i++) {
free(myMatrix[i].elements);
}
free(myMatrix);
return 0;
}
> ./a.out
How many myArray's do you want? 2
How many elements do you want in each array? 5
myMatrix[0].someData : 123
myMatrix[0].elements[0].field1 : 123
myMatrix[0].elements[0].field2 : 123
myMatrix[0].elements[0].field3 : 123
myMatrix[0].elements[1].field1 : 123
myMatrix[0].elements[1].field2 : 123
myMatrix[0].elements[1].field3 : 123
myMatrix[0].elements[2].field1 : 123
myMatrix[0].elements[2].field2 : 123
myMatrix[0].elements[2].field3 : 123
myMatrix[0].elements[3].field1 : 123
myMatrix[0].elements[3].field2 : 123
myMatrix[0].elements[3].field3 : 123
myMatrix[0].elements[4].field1 : 123
myMatrix[0].elements[4].field2 : 123
myMatrix[0].elements[4].field3 : 123
myMatrix[1].someData : 123
myMatrix[1].elements[0].field1 : 123
myMatrix[1].elements[0].field2 : 123
myMatrix[1].elements[0].field3 : 123
myMatrix[1].elements[1].field1 : 123
myMatrix[1].elements[1].field2 : 123
myMatrix[1].elements[1].field3 : 123
myMatrix[1].elements[2].field1 : 123
myMatrix[1].elements[2].field2 : 123
myMatrix[1].elements[2].field3 : 123
myMatrix[1].elements[3].field1 : 123
myMatrix[1].elements[3].field2 : 123
myMatrix[1].elements[3].field3 : 123
myMatrix[1].elements[4].field1 : 123
myMatrix[1].elements[4].field2 : 123
myMatrix[1].elements[4].field3 : 123
>
Please ensure the following:
for every malloc there should be a free
before using the memory that was allocated using malloc you must check whether malloc successfully allocated the memory block you've requested.
Something like this should work though it is not a great solution with so many seperate allocations, further down is a better solution. I have tried to make variable names descriptive of what they hold.
int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);
for(int i=0; i<lengthOfMyMatrix; ++i)
{
myMatrix[i].elements=new myElement[arrayOfSubArrayLengths];
myMatrix[i].someData=whatever;
}
to delete:
for(int i=0; i<lengthOfMyMatrix; ++i)
{
free( myMatrix[i].elements );
}
free( myMatrix );
However as I said that is not a great solution with so many allocations. It could cause some severe memory fragmentation depending on how large lengthOfMyMatrix is. Also so many calls to the allocator could slow things down depending once again on the size of lengthOfMyMatrix.
Here is a better solution:
int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
int sumOfSubArrayLengths=someNumber;
myArray* fullArray=(myElement*) malloc( sizeof(myElement) * sumOfSubArrayLengths);
myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);
int runningSum=0;
for(int i=0; i<lengthOfMyMatrix; ++i)
{
myMatrix[i].elements = &fullArray[runningSum];
runningSum += arrayOfSubArrayLengths[i];
myMatrix[i].someData = whatever;
}
to delete:
free( fullArray );
free( myMatrix );
In this fashion there are only two calls to the allocator no matter the various lengths. So there is far more memory fragmentation and less allocation overhead time.
The one downside to the second method is that if you are not careful with bounds checking it is very easy to corrupt data in the array without knowing since the memory 'belongs' to you and thus the OS will not kick you for an access violation.
Related
I was just messing around in C when I encountered this problem:
typedef struct {
int val;
} Test;
typedef struct {
Test* p;
} P;
int main() {
int a = 0;
P list[5];
while (a <= 5) {
Test new_test = {a};
list[a].p = &new_test;
++a;
}
for (int i = 0; i < 5; ++i) {
printf("%d ", list[i].p->val);
}
}
For some reason each value in the array is pointing to the same thing.
The output I expected was something like:
1 2 3 4 5
Instead I got:
5 5 5 5 5
Anyone know the reason for this?
The variable
Test new_test = {a};
is local to the block used as the loop body and its life ends on end of execution of the block, so dereferencing pointers pointing at the after execution of the block ends is illegal.
It looks like the compiler decided to reuse some of the memory space for each iteration.
To avoid this, allocate objects in a way that persists until you finish using them.
Also list[5] is out-of-range for P list[5]; and accessing the "element" is illegal. You have to allocate more elements to avoid out-of-range access.
/* add required headers */
#include <stdio.h> /* printf() */
#include <stdlib.h> /* malloc() */
typedef struct {
int val;
} Test;
typedef struct {
Test* p;
} P;
int main() {
int a = 0;
P list[5 + 1]; /* allocate enough element */
while (a <= 5) {
/* allocate non-local object */
Test* new_test = malloc(sizeof(*new_test));
if (new_test == NULL) return 1;
new_test->val = a;
list[a].p = new_test;
++a;
}
for (int i = 0; i < 5; ++i) {
printf("%d ", list[i].p->val);
}
}
#define MAX_NUM_STACKS_ALLOWED 10
#define MAX_PLATES_PER_STACK 5
#define NEW_STACKS_CREATION_INC 2
typedef struct stackOfPlates {
int currentStackIndex;
int currentStackTop[MAX_NUM_STACKS_ALLOWED];
int currentMaxStacks;
int **stackOfPlatesArray;
} stackOfPlates_t;
stackOfPlates_t *stackOfPlates_Init(void) {
stackOfPlates_t *stackOfPlates = (stackOfPlates_t *)malloc(sizeof(stackOfPlates));
stackOfPlates->stackOfPlatesArray = (int **)malloc(NEW_STACKS_CREATION_INC * sizeof(int *));
stackOfPlates->currentStackIndex = 0;
stackOfPlates->currentMaxStacks = NEW_STACKS_CREATION_INC;
int i;
for (i = 0; i < stackOfPlates->currentMaxStacks; i++) {
stackOfPlates->stackOfPlatesArray[i] = (int *)malloc(MAX_PLATES_PER_STACK * sizeof(int));
printf("%d\n", stackOfPlates->currentMaxStacks);
}
for (i = 0; i < MAX_NUM_STACKS_ALLOWED; i++) {
stackOfPlates->currentStackTop[i] = -1;
}
return stackOfPlates;
}
void main()
{
stackOfPlates_t *stackOfPlatesA;
stackOfPlatesA = stackOfPlates_Init();
}
The output of the above code is:
2 (expected),
0 (not expected, not sure how this field gets modified)
I'm trying to malloc the 2D array (stackOfPlates->stackOfPlatesArray). After allocating memory for the NEW_STACKS_CREATION_INC number of stacks, I allocate memory for MAX_PLATES_PER_STACK for every stack. During this operation, I find that my stackOfPlates->currentMaxStacks gets modified to 0.
Could someone please explain why?
In your code
malloc(sizeof(stackOfPlates));
should be
malloc(sizeof(*stackOfPlates));
As you want to allocate memory for the structure type not the pointer to structure type.
That said, see this: Do I cast the result of malloc?
I get the Error run-time check failure #3, and i have to initialize P and i know why but not how to do it.
Points is supposed to be a variable 2D array like float* points[3] for testing purposes its constant for now.
CVAPI(CvPOSITObject*) lvCreatePOSITObject( float points[5][3], int point_count )
{
CvPoint3D32f* P; //array of structs with int x,y,z
for(int i = 0; i< point_count; i++)
{
P[i].x = points[i][0];
P[i].y = points[i][1];
P[i].z = points[i][2];
}
return cvCreatePOSITObject(P,point_count);
}
I don't know much about OpenCV, but I think you should allocate some memory to store the data.
#include <stdlib.h> // add this to the head of the file to use malloc
CVAPI(CvPOSITObject*) lvCreatePOSITObject( float points[5][3], int point_count )
{
CvPoint3D32f* P; //array of structs with int x,y,z
P = malloc(sizeof(CvPoint3D32f) * point_count); // allocate some memory
for(int i = 0; i< point_count; i++)
{
P[i].x = points[i][0];
P[i].y = points[i][1];
P[i].z = points[i][2];
}
return cvCreatePOSITObject(P,point_count);
}
This code may be bad because this may not free the allocated buffer.
I'm trying to declare arrays with a variable size, given by user input.
So far I have something like this:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* rows;
int* colums;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = [ra];
o->colums = [ca];
return o;
}
int main(){
newObject(3,4);
}
I expected this wouldn't work, but I want something like this, and I don't know how to do it.
It looks like you're basically implementing a dynamic Matrix object here. You want something like:
typedef struct _object{
int rowsAmount;
int columsAmount;
int* matrix;
int** rows;
} object;
object* newObject(int ra, int ca){
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->matrix = malloc(ra * ca * sizeof(int));
o->rows = malloc(ra * sizeof(int*));
for (size_t i = 0; i != ra; ++i) o->rows[i] = o->matrix + (i * ca);
return o;
}
You should also create a destructor function destroyObject, which similarly frees all the memory allocated for o and o->matrix.
Edit:
However, your comment that:
"I'm just trying to learn c, this is only about the setting the size.
I just happened to try it with 2 arrays"
...makes this question somewhat confusing, because it indicates you are not, in fact, trying to create a matrix (2D array) despite your use of "row"/"column" terminology here, but that you simply want to understand how to dynamically allocate arrays in C.
If that's the case, an array in C is dynamically allocated using a pointer variable and malloc:
size_t array_size = 10; /* can be provided by user input */
int* array = malloc(sizeof(int) * array_size);
And then later, the dynamically-allocated array must be freed once you are finished working with it:
free(array);
To dynamically allocate a 2d array of data in C:
Allocate the memory for the entire data. That memory is pointed to by arrayData.
Allocate an 1D Array of pointers one for each row
Point those pointers to the memory address corresponding each row
Code:
int *arrayData = malloc(sizeof(int) * rows * columns);
int **array = malloc(sizeof(int*) * rows);
for(int i=0; i < rows;++i){
array[i] = arrayData + i * columns;
}
You can now access the memory as array[row][col].
You can create a array with size input from user with out a structure.
int *array1;
int size;
// get input from user
array1 = malloc(sizeof(int)*size);
// do your stuff
free(array1);
if you want a 2D array,
int **array2;
int row, col;
int i;
array2 = malloc(sizeof(int*)*row);
for(i=0;i<row;++i)
array2[i] = malloc(sizeof(int)*col);
//use the array
for(i=0;i<row;++i)
free(array2[i]);
free(array2);
if you really need a structure array, then allocate memory for it in your newObject() function
typedef struct _object{
int rowsAmount;
int columsAmount;
int** array;
//int* colums;
} object;
object* newObject(int ra, int ca){
int i;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->array = malloc(sizeof(int*)*ra);
for(i=0;i<ra;i++)
o-<array[i]=malloc(sizeof(int)*ca);
return o;
}
int main(){
newObject(3,4);
}
I think that quite often people use dynamic memory allocation when scoped variables can be used instead. For example, array sized from user's input can be allocated on stack without using malloc/free:
int array_size;
scanf("%d", &array_size);
if (array_size > 0) {
/* Allocate array on stack */
float array[array_size];
/* ... do smth with array ... */
}
/* Out of scope, no need to free array */
Of course if your data block is huge, heap memory is a must, but for small allocations scopes are just fine.
Easiest way is to use boost::multi_array
Not only will you get any number of dimensions, it's also stored very efficiently as a single contiguous block of memory rather than n dimensional array.
CPU's are designed to traverse arrays quickly, and you could potentially utilise caching/prefetch/pipelining features of the compiler using this.
Eg
// 2 dimensions
int xDim;
int yDim;
cin >> xDim; // From user..
cin >> yDim;
// Initialise array
boost::multi_array<int,2> my2dgrid(boost::extents[xDim][yDim]);
// Iterate through rows/colums
for(int j = 0 ; j < yDim-1; j++) { // Row traversal
for(int i = 0 ; i < xDim-1; i++) { // Column traversal
int value = grid[j][i]; // Get a value
grid[j][i] = 123; // set a value
// Do something...
}
#include <stdio.h>
#include <stdlib.h>
typedef struct _object{
int rowsAmount;
int columsAmount;
int **rows;
// int* colums;
} object;
object* newObject(int ra, int ca){
int r;
object* o = malloc(sizeof(object));
o->rowsAmount = ra;
o->columsAmount = ca;
o->rows = (int **)malloc(ra*sizeof(int *));
for(r=0;r<ra;++r)
o->rows[r] = (int*)malloc(ca*sizeof(int));
return o;
}
int main(){
object *obj= newObject(3,4);
obj->rows[2][3]=5;
return 0;
}
I am trying to build this project and for some reason the program hangs when I run it.
It works fine if i comment out the data cache lines. but it cannot make a call to makeCache for two different caches i dont know why any C experts know. Im new to c.
/*
* main.c
*
* Created on: Sep 16, 2010
* Author: TJ
*/
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int tag;
int valid;
int LRU;
int offset;
}directoryBlock;
typedef struct{
int setNumber;
directoryBlock blocks[];
}cacheSet;
typedef struct{
int cacheNumber;
cacheSet *sets[];
}cache;
cache* makeCache(cache *makeMe,int numberOfSets, int blocksPerSet);
int main(void)
{
int i = 0;
//cache * temp = makeCache(10,200);
i = 0;
int j = 0;
cache *instructions = malloc(sizeof(cache) + sizeof(cacheSet*));
cache *data = malloc(sizeof(cache) + sizeof(cacheSet*));
makeCache(instructions,20,300);
makeCache(data,20,300);
for(j=0;j < 20;j++)
{
for(i = 0; i < 300;i++)
{
printf("Data From Set %d Block %d, Valid %d, Tag %d, LRU %d, Offset %d\n",j,i
,instructions->sets[j]->blocks[i].valid,instructions->sets[j]->blocks[i].tag
,instructions->sets[j]->blocks[i].LRU,instructions->sets[j]->blocks[i].offset);
}
}
return 0;
}
cache* makeCache(cache *makeMe,int numberOfSets,int blocksPerSet)
{
int i = 0;
int j = 0;
for(j=0; j < numberOfSets;j++)
{
cacheSet *newSet = malloc(sizeof(cacheSet) + sizeof(directoryBlock)*blocksPerSet);
for(i = 0; i < blocksPerSet; i++)
{
directoryBlock temp;
temp.LRU = i*j;
temp.tag = i*j;
temp.offset = i*j;
temp.valid = i;
newSet->blocks[i] = temp;
}
makeMe->sets[j] = newSet;
}
return makeMe;
}
You're not allocating space for the cacheSet array, you have 20 cacheSets so try this with the "20 *" added to your lines:
cache *instructions = malloc(sizeof(cache) + 20 *sizeof(cacheSet*));
cache *data = malloc(sizeof(cache) + 20 * sizeof(cacheSet*));
In your main function you're allocating the memory for your cache. Since you have a function dedicated to creating the cache, it should allocate the memory. That function has the parameters to determine the total memory required. If you do it separately, you're repeating that information and require yourself to remember exactly how to allocate the memory. If the function makeCache does it for you, it will save pain later. Just be sure your documentation notes that the makeCache function allocates memory.
Your cache memory is incorrect, but not as pointed out before. Just sizeof(cache) is the right size. This will make room for the int and the cacheSet **. You should then allocate memory for the cacheSet array in each cache. Then you should allocate memory for each directoryBlock in each cacheSet in the cache.... kittens, cats, sacks, and wives...
So all your allocations should just be Thing *t sizof(Thing);
In psuedocode:
cache *c = malloc(sizeof(cache))
for 0 to number of cacheSets:
cacheSet *s = malloc(sizeof(cacheSet))
for 0 to number of blocks:
block *b = malloc(sizeof(block))
//fill in data
JD