C Programming weird struct setup - c

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

Related

Structure's int field gets modified after malloc() on the same structure's int*

#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?

Problem with free() function in C and memory-leaks

I've a problem about deallocating memory using free() in C.
My program generates a random genealogic tree using a matrix. This matrix can be very huge depending on the number of family members. The program seemed to work fine until I decided to generate more than one tree. I noticed that generating about 100 trees causes my 8GB RAM to fill! I'm sure I can make a better code to reduce the demand of memory, but my problem remains.
I use free() to deallocate memory and there's no error. I installed Valgrind to se what's happening and it says that about 100 million byte per tree are definitely lost. This means that free() doesn't work fine. I don't now where is the problem. I link some functions that I think are correlated to the problem.
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
The struct above is for the family.
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
This is for the members.
typedef struct{
int i;
int j;
int **val;
}int_mtx;
And the matrix.
In the main i call the function to initialize the tree:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
This is the frist part of init_family_n_gen():
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
This code is for mtxcalloc that initializes the matrix:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
And to conclude the code to deallocate the family:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
And the one to deallocate the matrix:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output
So I call the free_family(family_a) every time i need to regenerate the family but the memory still increases. (In the photo above the number of byte become 1 billion if i regenerate the family for 50 times).
Thanks for the support!
EDITED
I made a minimal reproducible example that emulates my original code. The structs and variables are the same but I changed the functions according to Weather Vane: they are all void and I pass them the double **.
The init_family_n_gen becomes:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
The main is:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
The only thing I added is this function(Is the code right?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
I noticed that the problem occours when i use the realloc function and i can't figure why. I link the images of Valgrind with and without the function mtxrealloc. (I see that there is aslo a 48 byte leak...).
Valgrind with realloc
Valgrind without realloc
Thanks again for your support!
This:
init_family(&family_a);
Causes this code from mtxcalloc to execute:
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
, with i, j = 100, 99. That is, you allocate space for 100 pointers, and for each one, you allocate space for 99 ints. These are then accessible via family_a->mtx.
Very shortly thereafter, you make this call:
mtxrealloc(&family->mtx, 5, 4);
, which does this, among other things:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
That loses all the pointers (*mtx)->val[5] through (*mtx)->val[99], each of which is the sole pointer to allocated space sufficient for 99 ints. Overall, sufficient space for 9405 ints is leaked before you even perform any computations with the object you are preparing.
It is unclear why you overallocate, just to immediately (attempt to) free the excess, but perhaps that's an artifact of your code simplification. It would be much better to come up with a way to determine how much space you need in advance, and then allocate only that much in the first place. But if you do need to reallocate this particular data, then you need to first free each of the (*mtx)->val[x] that will be lost. Of course, if you were going to reallocate larger, then you would need to allocate / reallocate all of the (*mtx)->val[x].

initializing array pointer to a struct

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.

Variable array size in c

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;
}

using malloc for block of structs

I am trying to allocate a block of memory, and store a list of structures without using multiple mallocs for each... this is just a generic example, I don't have the original code I was working with earlier, but this is the general idea, but my problem was that I was getting heap corruption when other parts of my code executed after the InitPoints() function call. I don't know what part of my code is illegal, but I suspect it is in the for loop of the InitPoints() function. I am trying to use this as table, then I can create additional tables of defined size if I ran out of memory and link them together... so kind of like a dynamic expanding array if that makes any sense.
typedef struct Tb{
POINT points;
POINT *next;
} TABLE;
typedef struct Pt{
int x;
int y;
}POINT;
POINT *mypoints;
int main() {
int size = 10;
int i = 0;
mypoints = InitPoints(size);
for(i=0; i < size; i++)
{
printf("mypoint [%d] = (%d,%d)\n",i, mypoints->x, mypoints->y);
mypoints = mypoints + sizeof(POINT);
}
// some other code...
// i.e. createThread(....)
return 0;
}
POINT* InitPoints(int size)
{
POINT *tmp;
POINT *orig;
int a = 10;
int b = 1000;
orig = (POINT*) malloc (sizeof(POINT) * size);
if(orig == NULL)
return NULL;
tmp = orig;
for (i = 0; i < size; i++)
{
tmp->x = a++;
tmp->y = b++;
tmp = tmp + sizeof(POINT);
}
return orig;
}
This is wrong:
mypoints = mypoints + sizeof(POINT);
You should review pointer arithmetic in C. Just use:
mypoints += 1; /* or something similar */
(There is a similar problem in your InitPoints function)
Here's one referemce:
http://www.eskimo.com/~scs/cclass/notes/sx10b.html
The problem is in this line:
tmp = tmp + sizeof(POINT);
It should be
++tmp;
The latter says to increment the pointer by one element; since it points to the structure, it increments by the size of the structure. The original code instead increments by n elements where n is the number of bytes in the structure. For example, if int is 32-bits, it will advanced by 8 elements.
This is why I would do it
for (i = 0; i < size; i++)
{
orig[i].x = a++;
orig[i].y = b++;
}
In C, adding an integer to a POINT* pointer advances the pointer not by that number of bytes, but by that number of POINT structures.
You have two places in your code where you add sizeof(POINT) to your pointer. Instead you should just add 1.

Resources