Array filling with malloc supposedly allocating less memory than needed - c

I'd like to know why I'm having this behavior:
This is the code that I'm using:
matriz2= (float**) malloc (sizeof(float**));
for (int m=0;m<36;m++)
{
matriz2[m]=(float *) malloc(36*sizeof(float*));
}
for (int k=0;k<36;k++)
{
for (int l=0;l<36;l++)
{
matriz2[k][l]=i;
i++;
printf("%f\n ",matriz2[k][l]);
}
}
I've checked some things about the memory allocation that malloc does.
The following code runs nice if instead matriz2[m]=(float *) malloc(36*sizeof(float*)); I put (float *) malloc(35*sizeof(float*));
But that doesn't happen if I do it with 34.
I've also checked that the following code works, indeed it works up to changing all 3s for 4s, with 5 it fails:
matriz2= (float**) malloc (sizeof(float**));
for (int m=0;m<3;m++)
{
matriz2[m]=(float *) malloc(sizeof(float*));
}
for (int k=0;k<3;k++)
{
for (int l=0;l<3;l++)
{
matriz2[k][l]=i;
i++;
printf("%f\n ",matriz2[k][l]);
}
}
Although from what I understand from malloc it shouldn't be able to fill the array and a segmentation fault should happen.
Why can I fill the array this way?
Thanks.

Your code
matriz2= (float**) malloc (sizeof(float**));
for (int m=0;m<36;m++) {
matriz2[m]=(float *) malloc(36*sizeof(float*));
}
reserves space for only one pointer, but assigns 36 pointers and therefore exceeds array bounds and yields undefined behaviour (crash, "funny" output, ...).
Generally you are mixing up the pointers to pointers to floats semantics in your code (e.g. matriz2= (float**) malloc (sizeof(float**)) should be matriz2= (float**) malloc (36*sizeof(float*))).
Let's start from a single dimension. If you allocate space for a sequence of 36 float values, you will write malloc(36 * sizeof(float)). The result of this will be a pointer to the first float value of this sequence, and the type of the result is therefore float * (BTW: in contrast to C++, in C you should not cast the result of malloc). Note that - for getting a sequence of float values, you write 36 * sizeof(float), and not 36 * sizeof(float*), which would be a sequence of pointers to floats. Hence, a single dimension is allocated as follows:
float *row = malloc(36 * sizeof(float));
If you now have a sequence of such rows (each having type float *), you need to allocate space for a sequence of such pointers, i.e. malloc (36 * sizeof(float*)), and the result is a pointer to the first pointer of this sequence of pointers. Hence, the result type is float**:
float **matrix = malloc(36 * sizeof(float*))
Then you can reserve space for each row and assign it:
float **matrix = malloc(36 * sizeof(float*)) // sequence of pointers to rows
for (int m=0;m<36;m++) {
matrix[m]=malloc(36*sizeof(float)); // row, i.e. sequence of floats
}
Hope it helps.

your initial malloc is too small (35 times :))

Related

Can someone please explain this. It deals with malloc and global array in C

If I'm trying to create a global array to hold an arbitrary number of integers in this case 2 ints. How is it possible that I can assign more numbers to it if I only allocate enough space for just two integers.
int *globalarray;
int main(int argc, char *argv[]) {
int size = 2;
globalarray = malloc(size * sizeof(globalarray[0]));
// How is it possible to initialize this array pass
// the two location that I allocated.
for (size_t i = 0; i < 10; i++) {
globalarray[i] = i;
}
for (size_t i = 0; i < 10; i++) {
printf("%d ", globalarray[i]);
}
printf("%s\n", "");
int arrayLength = sizeof(*globalarray)/sizeof(globalarray[0]);
printf("Array Length: %d\n", arrayLength);
}
When I run this it gives me
0 1 2 3 4 5 6 7 8 9
Array Length: 1
So I wanted to know if someone could clarify this for me.
(1) Am I creating the global array correctly?
(2) Why is the array length 1? When I feel that it should be 2 since I malloced the pointer for 2.
And background info on why I want to know this is because I want to create a global array (shared array) so that threads can later access the array and change the values.
How is it possible to initialize this array pass the two location that I allocated.
Short answer: This is undefined behaviour and anything can happen, also the appearance that it worked.
Long answer: You can only initialize the memory you've allocated, it
doesn't matter that the variable is a global variable. C doesn't prevent you from
stepping out of bounds, but if you do, then you get undefined behaviour and anything can happen
(it can "work" but it also can crash immediately or it can crash later).
So if you know that you need 10 ints, then allocate memory for 10 int.
globalarray = malloc(10 * sizeof *globalarray);
if(globalarray == NULL)
{
// error handling
}
And if you later need more, let's say 15, then you can use realloc to increase
the memory allocation:
globalarray = malloc(10 * sizeof *globalarray);
if(globalarray == NULL)
{
// error handling
// do not contiue
}
....
// needs more space
int *tmp = realloc(globalarray, 15 * sizeof *globalarray);
if(tmp == NULL)
{
// error handling
// globalarray still points to the previously allocated
// memory
// do not continue
}
globalarray = tmp;
Am I creating the global array correctly?
Yes and no. It is syntactically correct, but semantically it is not, because you are
allocating space for only 2 ints, but it's clear from the next lines that
you need 10 ints.
Why is the array length 1? When I feel that it should be 2 since I malloced the pointer for 2.
That's because
sizeof(*globalarray)/sizeof(globalarray[0]);
only works with arrays, not pointers. Note also that you are using it wrong in
two ways:
The correct formula is sizeof(globalarray) / sizeof(globalarray[0])
This only works for arrays, not pointers (see below)
We sometimes use the term array as a visual representation when we do stuff
like
int *arr = malloc(size * sizeof *arr)
but arr (and globalarray) are not arrays,
they are pointers. sizeof returns the amount in bytes that the
expression/variable needs. In your case *globalarray has type int and
globalarray[0] has also type int. So you are doing sizeof(int)/sizeof(int)
which is obviously 1.
Like I said, this only works for arrays, for example, this is correct
// not that arr here is not an array
int arr[] = { 1, 2, 3, 4 };
size_t len = sizeof arr / sizeof arr[0]; // returns 4
but this is incorrect:
int *ptr = malloc(4 * sizeof *ptr);
size_t len = sizeof ptr / sizeof ptr[0]; // this is wrong
because sizeof ptr does not returns the total amount of allocated
bytes, it returns the amount of bytes that a pointer needs to be stored in memory. When you are dealing with
pointers, you have to have a separate variable that holds the size.
C does not prevent you from writing outside allocated memory. When coding in C it is of the utmost importance that you manage your memory properly.
For your second question, this is how you would want to allocate your buffer:
globalarray = malloc(sizeof(int) * size);
And if you are on an older version of C than c11:
globalarray = (int*) malloc(sizeof(int) * size);

reading and printing matrix using pointer to pointer method

I wrote a program for reading and printing the matrix without making use of array of pointers. The program is reading and printing matrix correctly, but it crashes after the execution. There are no warnings in the program. Unable to find what is wrong with the program. I am using Codeblock+mingw
Also is this method of using pointer to pointer for two dimensional matrix is OK or any better method?
#include <stdio.h>
#include <malloc.h>
int main()
{
int numCols=2;
int numRows=2;
int *cols;
int rowCount;
int colCount;
cols=(int*) malloc(numCols*sizeof(int));
int **rows;
rows= (int**) malloc(numRows*sizeof(cols));
printf("Filling the rows and Columns\n");
for(rowCount=0;rowCount<numRows;rowCount++)
{
printf("Fill Row Number %d\n",rowCount);
for(colCount=0;colCount<numCols;colCount++)
{
printf("Enter the value to be read\n");
scanf("%d",(*(rows+rowCount)+colCount));
}
}
// Printing the values
for(rowCount=0;rowCount<numRows;rowCount++)
{
printf("Print Row Number %d\n",rowCount);
for(colCount=0;colCount<numCols;colCount++)
{
printf("%d\t",*(*(rows+rowCount)+colCount));
}
printf("\n");
}
free(rows);
free(cols);
return 0;
}
You're not allocating memory in the right manner. Your program crashes because of illegal memory access it makes.
What's Cols array for; as you're never storing any integer in it and its extra. Second rows is a an array int* not int. One of the ways to allocate a 2D array will be
int** matrix;
matrix = (int **)malloc(sizeof(int *));
matrix[0] = (int *)malloc(sizeof(int) * c * r);
//To access elements
for(rowCount=0;rowCount<numRows;rowCount++)
{
printf("Fill Row Number %d\n",rowCount);
for(colCount=0;colCount<numCols;colCount++)
{
printf("Enter the value to be read %d %d \n", rowCount, colCount);
scanf("%d",(*matrix+rowCount*numCols)+colCount);
}
}
//free it as
free(matrix);
Its always a good practice to allocate and access row-wise in C to so that memory fetches are not bottle-neck.
Update
Yes you can allocate memory like this.
rows= (int**) malloc(numRows * numCols * sizeof(int)); //Yes sizeof(int).
Its perfectly legal statement in C. It will allocate numRows * numCols sized array of integer pointers with each element of size equal to sizeof(int).
It may cause trouble on 64bit platform where pointers are 8 byte long.
Even assuming it to be 32bit platform there is another problem. How will you dereference rows for your intended purpose? rows[i] will be a pointer to integer i.e. int* type; but doing scanf on that will give you a segmentation fault as row[i] will contain some garbage value and might lead you to some unwanted area in memory.

Correct way to allocate and free arrays of pointers to arrays

I want to create an array of pointers to arrays of 3 floats. What is the correct way to do this?
float *array1[SIZE]; // I think it is automatically allocated
// OR
float **array1 = calloc(SIZE, sizeof(float*));
free(array1);
for (int i = 0; i < SIZE; i++) {
array1[i] = (float[]){0,0,0};
// OR
array1[i] = calloc(3, sizeof(float));
}
Then how would I free the data? I'm pretty sure just free(array1); wouldn't work, so would I free each pointer in the array then free the array, or since I allocated three floats, would I free each float, then each 3 float array, then the whole array???
If you know the array size at compile time (and you do, if SIZE is a compile-time constant), you should just declare a two-dimensional array. You don't need to free this at all (and must not).
float array1[SIZE][3];
You need to use calloc, and to create an array of pointers, only if the dimensions are not known at compile time. In this case, there should be one call to free for each call to calloc. And since you cannot use an array after you free it, you need to free the row arrays before you free array1.
float **array1 = calloc(nrows, sizeof (float *));
for (int i=0; i < nrows; i++)
array1[i] = calloc(3, sizeof(float));
// Use it...
// Now free it
for (int i=0; i < nrows; i++)
free(array1[i]);
free(array1);
Edit: if you won't be rearranging the pointers (to sort the rows in-place, for example), you can do all of this with just one calloc (and one call to free afterwards):
float (*array1)[3] = calloc(3*nrows, sizeof (float));
That's because the number of columns is known at compile-time, and that's all the pointer arithmetic needs to know. Then you can write things like array1[i][j], and you can still pass around array1[i] as if it was a real pointer to a row. C is great that way, take advantage of it!
A general rule is that for each time you call malloc() or calloc() you will need to do a free() call on the returned pointer.
If you want a two dimensional array with compile-time known size, just use a two dimensional array! float val[5][3] is perfectly valid.
If you want a two dimensional array and you don't know it's size during compile-time, you most probably want to use a standard, single diemensional calloc() and an appropriate getter.
#define ARR_COLUMNS 10
#define ARR_ROWS 10
float* arr = calloc (ARR_COLUMNS * ARR_ROWS, sizeof(float));
int get(float* arr, int x, int y) {
if (x<0 || x>= ARR_COLUMNS) return 0;
if (y<0 || y>= ARR_ROWS) return 0;
return arr[ARR_COLUMNS*y+x];
}
void set (int* arr, int x, int y, float val) {
if (x<0 || x>= ARR_COLUMNS) return;
if (y<0 || y>= ARR_ROWS) return;
arr[ARR_COLUMNS*y+x] = val;
}
Of course replace the defines with appropriate variables.
By doing so you will:
save yourself costly allocs and frees
have less fragmented memory
simplify your possible realloc calls
ensure the data is cached better and accessed without the common [x][y] vs [y][x] iteration cache problem.
I want to create an array of pointers to arrays of 3 floats. What is the correct way to do this?
Why do you want an array of pointers to arrays? Wouldn't an array of arrays be sufficient? (Keep in mind that arrays are already pointer-like, they are not passed by value, rather the address of the first element is passed when an array is passed as an argument to a function).
// stack allocation, no need to free
float array[SIZE][3];
for (int i = 0; i < SIZE; i++) {
// do something with array[i][0], array[i][1], array[i][2]
}
Then how would I free the data?
In this case you wouldn't, since the data is stack allocated (will be cleaned up automatically once out of scope). Just remember the rule of thumb is that for every memory allocation you make, a corresponding free is necessary. So if you allocate memory for an array of floats, as in
float* arr = malloc(sizeof(float) * 3); // array of 3 floats
Then you only need to call free on the array that you malloc'd, no need to free the individual floats. If you perform nested allocation as in
// array of length SIZE, consisting of float pointers
float** arr = malloc(sizeof(float*) * SIZE);
// allocate the array of 3 floats at each index
for (int i = 0; i < SIZE; i++)
arr[i] = malloc(sizeof(float) * 3);
Then you will need to perform a free for every malloc, as in
// free the individual arrays
for (int i = 0; i < SIZE; i++)
free(arr[i]);
// free the array of arrays
free(arr);
The lesson to take away here is to avoid dynamic allocation of arrays all-together. Stick with either std::vector or stack-allocated arrays.

free a double pointer

I created a 2-D matrix using double pointer like that:
int** pt; pt = (int*) malloc(sizeof(int)*10);
I know that a pointer is freed like that
free(ptr);
How can we free the double pointer?
What if we print something and later freed that memory and exit the program? Does the final memory consist of that which we used or it will be same as initial?
Say you have a matrix mat
int** mat = malloc(10 * sizeof(int*));
for (int i=0; i<10; ++i) {
mat[i] = malloc(10 * sizeof(int));
}
then you can free each row of the matrix (assuming you have initialized each correctly beforehand):
for (int i=0; i<10; ++i) {
free(mat[i]);
}
then free the top-level pointer:
free(mat);
For your second question: if you allocate memory and use it, you will change that memory, which will not be "reverted" even if you free it (although you will not be able to access it reliably/portably any more).
Note: the top-level malloc is using sizeof(int*) as you are allocating pointer-to-ints, not ints -- the size of int* and int are not guaranteed to be the same.
If your matrix isn't "ragged", i.e. all rows have the same length, you might want to consider:
Accessing it manually, i.e. just treat it as a 1D array of values, and keep a separate width value. To access an element at (x,y) use mat[y * width + x].
If you really want the convenience of mat[y][x], you can improve it by doing a single call to malloc() that allocates both the pointer array and all the rows, then initializing the pointers to point at each row. This has the advantage that it can all be free:ed with a single free(mat); call.
The second approach would look something like this:
double ** matrix_new(size_t width, size_t height)
{
double **p = malloc(height * sizeof *p + width * height * sizeof **p);
double *e1 = (double *) (p + height);
size_t i;
for(i = 0; i < height; ++i)
p[i] = e1 + i * width;
return p;
}
Note: the above is un-tested, and production code should obviously check for failure before using p.
For the first question, I'll tell you the rule of thumb.
The number of times you call free() should be equal to the number of times you call malloc() + the number of times you call calloc().
So if you allocated in such a way that you made a pointer to pointers to ints, and then used malloc() on each pointer to ints, then you'll free "row" number of times, where each free() is for each pointer to ints.
And a final free() is called on the pointer to pointers to ints. That will balance out the malloc() + calloc() with free() calls.

Dynamic allocation (malloc) of contiguous block of memory

For an assignment, I have to allocate a contiguous block of memory for a struct, but I'm first trying to do it with a 2D array of ints first and see if I understand it correctly. We had an example in the book that creates a block of memory for the pointer array (rows), and then initializes the cols and points the pointer to them. This example was:
int **CreateInt2D(size_t rows, size_t cols)
{
int **p, **p1, **end;
p = (int **)SafeMalloc(rows * sizeof(int *));
cols *= sizeof(int);
for (end = p + rows, p1 = p; p1 < end; ++p1)
*p1 = (int *)SafeMalloc(cols);
return(p);
}
void *SafeMalloc(size_t size)
{
void *vp;
if ((vp = malloc(size)) == NULL) {
fputs("Out of mem", stderr);
exit(EXIT_FAILURE);
}
return(vp);
}
I basically need to do what the above code does except make it one contiguous block of memory. The constraint is I'm only allowed to call malloc once, and then I have to use pointer math to know what to initialize the pointers to. So I thought I would initialize enough memory with something like:
int *createInt2D(size_t rows, size_t cols)
{
malloc(rows * sizeof(int *) + (row + cols) * sizeof(int));
}
But that doesn't seem quite right since I would think I would have to typecast the void * returned from malloc, but it's a combination of int and int*. So I'm not quite sure if I'm on the right track. Thoughts?
If you want a contiguous array, you should malloc(rows * cols * sizeof(int)).
Then you'd access arr[x, y] like:
arr[x * cols + y]
You are on the right track. The block returned by malloc is guaranteed to be aligned properly for either int * or int; you can use it for either. Typecasting isn't a one time operation.
If you are going to use array[row, col] addressing exclusively, you can get by without allocating extra space for the row pointers. If you would like to be able to use array[row] to get an int * column list, you'll have to include space for the column pointers in your allocation.
Hope that's enough to help with your exercise.
malloc((row * cols) * sizeof(int));
It's row*cols which is number of elements in the 2D array and not row+cols.
No need to multiply by the size of int *. That's only used to allocate the pointers for the rows. Same too with the sum of rows and cols. It's sufficient to allocate (rows * cols) * sizeof whatever structure is being allocated.

Resources