Contiguous memory allocation for 2D array --- freeing the memory - c

I am facing a heap crash during free() when I run this program, but I am successful if I do debug using F10 (in Visual studio 2010).
My piece of code:
The below code is used to free. Can someone please explain deallocation for 2D array in this case?
void Deallocate2D ( SINT32 **pAccess, UINT8 i_ubyNoOfRows )
{
int i;
UINT8 *elem;
if ( NULL == pAccess )
{
printf ( "%d>Invalid Params\n", __LINE__ );
return;
}
printf ( "\nDeallocate 2D Array..................\n" );
/* Include the code to deallocate the 2D array */
{
free(pAccess);
}
}
The below code is used for memory allocation:
SINT32 Allocate2D (
SINT32 ***pAccess,
UINT8 i_ubyNoOfRows,
UINT8 i_ubyNoOfCols )
{
SINT32 nResult = -1;
SINT32 **pAc = NULL;
UINT8 *pubyPositioner;
UINT32 unTotalSize;
int i;
//unTotalSize = i_ubyNoOfRows * i_ubyNoOfCols;
printf ( "\nAllocate 2D Array..................\n" );
/* Include the code to allocate the 2D array */
{
/*Contiguous memallocation pAc*/
pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows);
if(pAc)
pubyPositioner = (UINT8*)malloc(sizeof(UINT8) * i_ubyNoOfCols);
if(pubyPositioner)
for(i = 0; i < i_ubyNoOfCols; ++i)
pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);
*pAccess = pAc;
/*Non contugious allocation*/
/*
pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows );
*pAccess = pAc;
if(pAc)
for(i= 0; i < i_ubyNoOfRows; ++i){
pAc[i] = (SINT32*)malloc(sizeof(SINT32*) + (i * i_ubyNoOfRows) );
if(pAc[i])
for(j = 0; j < i_ubyNoOfCols; ++j)
pAc[i][j] = (UINT8)malloc(sizeof(UINT8) + (i_ubyNoOfRows * i_ubyNoOfCols) );
}
*/
if(*pAccess != NULL)
nResult = 0;
}
if ( NULL == pAccess )
{
printf ( "%d>Invalid Params\n", __LINE__ );
return -1;
}
return nResult;
}
The code to fill array and print array:
SINT32 Fill2D (
SINT32 **pnAccess,
SINT32 *pnData,
UINT8 i_ubyNoOfRows,
UINT8 i_ubyNoOfCols )
{
SINT16 wRIndex, wCIndex, wDataIndex = 0;
printf ( "\nFill 2D Array..................\n" );
/* Include the code to fill the 2D array with the 1D values */
{
for(wRIndex = 0 ; wRIndex < 3; ++wRIndex)
for(wCIndex = 0; wCIndex < 3; ++wCIndex)
pnAccess [wRIndex][wCIndex] = pnData[wDataIndex++];
}
if ( ( NULL == pnAccess ) \
|| ( NULL == pnData ) )
{
printf ( "%d>Invalid Params\n", __LINE__ );
return -1;
}
return 0;
}
SINT32 Print2D (
SINT32 **pnAccess,
UINT8 i_ubyNoOfRows,
UINT8 i_ubyNoOfCols )
{
SINT16 wRIndex, wCIndex;
if ( NULL == pnAccess )
{
printf ( "%d>Invalid Params\n", __LINE__ );
return -1;
}
printf ( "\n2D Array..................\n\n" );
/* Include the code to Print the 2D array in matrix format */
{
for(wRIndex = 0 ; wRIndex < i_ubyNoOfRows; ++wRIndex)
{
if(wRIndex % 2 == 0)
printf("\n");
for(wCIndex = 0; wCIndex < i_ubyNoOfCols; ++wCIndex)
printf("%d ", pnAccess[wRIndex][wCIndex]);
}
}
return 0;
}
The below code is kind of entry point:
void Test2DArray ( void )
{
SINT32 **pnData = NULL;
SINT32 nData1[] = { 10, 15, 20, 15, 20, 25, 10, 25, 20 };
SINT32 nData2[] = { 70, 75, 80, 65, 90, 25, 30, 35, 80 };
printf ( "\n==================================\n" );
printf ( "Test 2D Array..................\n" );
printf ( "==================================\n\n" );
if ( Allocate2D( &pnData, 3, 3 ) != -1 )
{
if ( Fill2D( pnData, nData1, 3, 3 ) != - 1 )
{
if ( NULL != pnData )
{
Print2D ( pnData, 3, 3 );
Deallocate2D ( pnData, 3 );
}
}
}
if ( Allocate2D( &pnData, 3, 3 ) != -1 )
{
if ( Fill2D( pnData, nData2, 3, 3 ) != - 1 )
{
if ( NULL != pnData )
{
Print2D ( pnData, 3, 3 );
Deallocate2D ( pnData, 3 );
}
}
}
}

/*Contiguous memallocation pAc*/
pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows);
if(pAc)
pubyPositioner = (UINT8*)malloc(sizeof(UINT8) * i_ubyNoOfCols);
if(pubyPositioner)
for(i = 0; i < i_ubyNoOfCols; ++i)
pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);
This is not contiguous memory allocation! It is a pointer-based lookup table which is allocated in one segment, pointing at a chunk of memory allocated in another segment.
Correct code for allocating a true 2D array would be:
SINT32 (*pAc)[ubyNoOfCols] = malloc( sizeof(SINT32[i_ubyNoOfCols][i_ubyNoOfRows]) );
...
free(pAc);
Note that this will only compile on a C compiler, so you can't use Visual Studio.
Can someone please explain deallocation for 2D array in this case?
free(pAccess);
Looks like the code only deallocates the pointer lookup table and not the actual data. So I suppose that is a bug: the code contains memory leaks.

Lets take a look at your allocation code:
pAc = (SINT32**)malloc(sizeof(SINT32*) * i_ubyNoOfRows);
if(pAc)
pubyPositioner = (UINT8*)malloc(sizeof(UINT8) * i_ubyNoOfCols);
if(pubyPositioner)
for(i = 0; i < i_ubyNoOfCols; ++i)
pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);
So, you are first allocating memory for i_ubyNoOfRows pointers. This is fine.
Then you proceed to allocate i_ubyNoOfCols bytes, (3 bytes in your test case), but you need space for i_ubyNoOfCols*i_ubyNoOfRows integers (3*3*4 = 36 bytes in your test case, assuming int is a 32-bit type).
When you proceed to initialize your memory, you trod on data vital for malloc() and free() to function properly.
A telltale sign of one half of your mistake is the cast in the line pAc[i] = (SINT32*)pubyPositioner + (i * i_ubyNoOfCols);. It shows that you used a wrong type for pubyPostitioner.
Ps: You have two 3s hardcoded in Fill2D(), even though this function gets the correct width and height passed as arguments.

In my question,I wanted to allocate memory for 2D array then free it.
After some study, i have explained my understanding as below
Allocate memory using array of pointers
double **p;
int i;
p= malloc(rows * sizeof(*p));
for(i= 0; i<rows;++i)
p[i] = malloc(cols * sizeof(double));
...
...
for(i=0;i<rows;i++)
free(p[i]);
free(p);
allocation using pointer lookup table
double **p;
double *elem;
elem = malloc(rows * cols * sizeof(double));
p = malloc(cols * sizeof(double*));
for (i = 0; i<rows;++i)
p[i] = elem + ( i*cols);
free(p);
Contiguous Allocation
double **p;
p = malloc( rows * cols * sizeof(double*));
/*Accessing / printing values ... assume values are assinged to this array*/
for(i=0; i <rows; ++i)
for(j = 0; j< cols; ++j)
printf("%d",p[j + (i * cols)]);
free(p)

Related

How to correctly initialise a struct in C

I'm working on a small project in C and I want to allocate structs in a function and add them to an array of structs.
For some reason, when I go to print the contents of the array of structs, I appear to start printing from unallocated memory.
A minimum working example is provided below:
#include <stdio.h>
#include <stdlib.h>
// This struct simply stores a list and its size
struct list {
int* values;
size_t size;
};
// This function initialises an array of lists
// of size len, which each list (i.e. list.values)
// having a size of list_len
// `lists` is an array of pointers to lists
void list_init(struct list** lists, size_t len, size_t list_len) {
for (size_t i = 0; i < len; i++) {
struct list list;
list.values = malloc(sizeof(int) * list_len);
list.size = list_len;
lists[i] = &list;
}
}
void main() {
int len = 3;
struct list* lists[len];
list_init(lists, len, 5);
// Print lists
for (size_t i = 0; i < len; i++) {
printf("list %zu: ", i);
printf("size: %zu\n", lists[i]->size);
for (size_t j = 0; j < 5; j++) { // Using 5 instead of lists[i]->size for obvious reasons
printf("%d ", lists[i]->values[j]);
}
printf("\n");
}
}
The output I would expect from this is:
list 0: size: 5
0 0 0 0 0
list 1: size: 5
0 0 0 0 0
list 2: size: 5
0 0 0 0 0
but instead I get:
list 0: size: 5
0 0 0 0 0
list 1: size: 140727488332736
0 0 0 0 0
list 2: size: 140727488332736
0 0 0 0 0
which is a pretty clear sign that I'm accessing memory that I'm not supposed to.
I noticed that rather than declaring the list with struct list list;, if I declare the list by allocating memory to a pointer with struct list* list = malloc(sizeof(struct list)); the program gives the expected output. Why is that? If I want to create the object, rather than a pointer, how can I do that properly.
P.S.: I am aware that I could just initialise list as a pointer. This question is mostly asking why can't I initialise it as an object
You save the references to the same local variable and it is an UB. Also malloced memory is lost. Your main is also wrong.
I would do it this way (calloc is used as in main you print not initialized allocated memory):
typedef struct list {
size_t size;
int values[];
}list;
list **list_init(list **array, size_t size, size_t list_len)
{
list **wrk;
if(!array) wrk = malloc(sizeof(*wrk) * size);
else wrk = array;
if(wrk)
for (size_t i = 0; i < size; i++) {
list *list = calloc(1, sizeof(*list) + list_len * sizeof(list -> values[0]));
/* check for allocation errors!!!! */
list -> size = list_len;
wrk[i] = list;
}
return wrk;
}
int main(void) {
size_t len = 3;
list **lists;
/* if you pass NULL it will create the list of lists itself */
lists = list_init(NULL, len, 5);
/* check for allocation errors!!!! */
// Print lists
for (size_t i = 0; i < len; i++) {
printf("list %zu: ", i);
printf("size: %zu\n", lists[i]->size);
for (size_t j = 0; j < 5; j++) { // Using 5 instead of lists[i]->size for obvious reasons
printf("%d ", lists[i]->values[j]);
}
printf("\n");
}
for (size_t i = 0; i < len; i++) free(lists[i]);
free(lists);
}
https://godbolt.org/z/9TPe1sM1a
These statements within the function list_init
struct list list;
//...
lists[i] = &list;
does not make a sense because the local object list will not be alive after exiting the function. So you will have an array of invalid pointers of the type struct list *.
You need to allocate dynamically each object of the type struct list that will be pointed to by an element of the array.
The function can be declared and defined for example the following way
size_t list_init( struct list **lists, size_t len, size_t list_len )
{
size_t count = 0;
for ( size_t i = 0; i < len; i++ )
{
lists[i] = malloc( sizeof( struct list ) );
if ( lists[i] != NULL )
{
++count;
lists[i]->size = 0;
lists[i]->values = malloc( sizeof( int ) * list_len );
if ( lists[i]->values != NULL ) lists[i]->size = list_len;
}
}
return count;
}
Also as the function does not initialize the allocated array pointed to by the data member values then this loop in main
for (size_t j = 0; j < 5; j++) { // Using 5 instead of lists[i]->size for obvious reasons
printf("%d ", lists[i]->values[j]);
}
will invoke undefined behavior.
You could zero initialize the arras by using calloc instead of malloc. For example
lists[i]->values = calloc( list_len, sizeof( int ) );
And pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
Here is your updated program.
#include <stdio.h>
#include <stdlib.h>
// This struct simply stores a list and its size
struct list
{
int* values;
size_t size;
};
size_t list_init( struct list **lists, size_t len, size_t list_len )
{
size_t count = 0;
for ( size_t i = 0; i < len; i++ )
{
lists[i] = malloc( sizeof( struct list ) );
if ( lists[i] != NULL )
{
++count;
lists[i]->size = 0;
lists[i]->values = calloc( list_len, sizeof( int ));
if ( lists[i]->values != NULL ) lists[i]->size = list_len;
}
}
return count;
}
int main(void)
{
size_t len = 3;
struct list* lists[len];
list_init(lists, len, 5);
// Print lists
for ( size_t i = 0; i < len; i++ )
{
printf( "list %zu: ", i );
if ( lists[i] != NULL )
{
printf( "size: %zu\n", lists[i]->size );
for (size_t j = 0; j < lists[i]->size; j++)
{
printf( "%d ", lists[i]->values[j] );
}
printf("\n");
}
}
return 0;
}
The program output is
list 0: size: 5
0 0 0 0 0
list 1: size: 5
0 0 0 0 0
list 2: size: 5
0 0 0 0 0
Of course you need to add a code to your program that will free all the allocated memory in the function list_init.

free(): invalid next size (fast) for resizable vector

I'm trying to implement a resizable vector in C without using the realloc and calloc functions. However, when I try to push a lot of values to the back of the array, I get a free(): invalid next size error. How can I remedy this?
I tried freeing the array right before I re-malloc it( the commented out block) but that causes a seg fault rather than the current error.
typedef struct {
size_t size;
size_t maxsize;
int* array;
}
vector_int_t;
// Push a new value into the vector_int_t, allocate just enough memory if
// the internal array is full.
void vector_int_push_back_v1( vector_int_t* this, int value )
{
if( this->size == this->maxsize ) {
int* temp = malloc( 4 * (sizeof( this->maxsize)+1) );
size_t j = 0;
for( size_t i = 0; i < this->maxsize; i++ ) {
temp[j] = this->array[i];
j++;
}
temp[this->size] = value;
/*if( this->size == 0 ) {
this->array = malloc( 4 * (sizeof(this->maxsize)+2));
this->size++;
this->maxsize++;
size_t z = 0;
for( size_t y = 0; y < this->maxsize; y++ ) {
this->array[z] = temp[y];
z++;
}
}
else {
free( this->array );*/
this->array = malloc( 4 * (sizeof(this->maxsize)+2) );
this->size++;
this->maxsize++;
size_t h = 0;
for( size_t k = 0; k < this->maxsize; k++ ) {
this->array[h] = temp[k];
h++;
}
free( temp );
}
else {
this->size++;
this->maxsize++;
this->array[this->size - 1] = value;
}
}
This error typically happens when you write out of bounds of the allocated memory.
A very likely culprit is the use of sizeof in e.g. malloc( 4 * (sizeof( this->maxsize)+1) ).
If you want to allocate this->maxsize + 1 elements, you should use just that not sizeof.
But you should use sizeof to get the size of each element (e.g. sizeof *temp).
So the statement
int* temp = malloc( 4 * (sizeof( this->maxsize)+1) );
should really look like
int* temp = malloc( sizeof *temp * (this->maxsize+1) );

reallocation of 2d arrays in c

I want to reallocate a 2d array, so that the arrays in the second array become bigger, so the things I want to store are bigger than the arrays I want to store them in and I want to make the arrays bigger. The problem is that I do not really know how to do this. I got it to compile without errors, but in Valgrind I saw a lot of memory errors, so I do something wrong. I saw a previous question about this here but I do not really understand it, so any help and explanation on how to do this would be greatly appreciated.
I have this so far.
int **create2darray(int a, int b) {
int i;
int **array;
array = malloc(a * sizeof(int *));
assert(array != NULL);
for (i = 0; i < a; i++) {
array[i] = calloc(b, sizeof(int));
assert(array[i] != NULL);
}
return array;
}
int **reallocArray(int **array, int size, int i) {
int i;
int **safe_array;
safe_array = realloc(*array ,2 * size);
assert(safe_array != NULL);
array = safe_array;
return array;
}
void free2DArray(int **array, int m) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
}
int main(int argv, char *argc[]) {
int i;
int size;
int **testArray = create2darray(1, 10);
size = 10;
for(i = 0; i < size; i++) {
testArray[0][i] = 2;
}
testArray[0] = reallocArray(testArray, size, 0);
size = 2 * size;
for(i = 9; i < size; i++) {
testArray[0][i] = 3;
}
for(i = 0; i < size; i++) {
printf("%d", testArray[0][i]);
free2DArray(testArray, size);
}
return 0;
}
You need a function reallocArray which realaoctes the outer array and all the inner arrays too.
Adapt youre code like this:
#include <malloc.h>
int **reallocArray( int **array, int oldSizeA, int newSizeA, int newSizeB )
{
// realloc the array of pointers ( allocates new memory if array == NULL )
int **safe_array = realloc( array, newSizeA * sizeof( int* ) );
assert(safe_array != NULL);
if ( safe_array == NULL )
return array;
array = safe_array;
// realloc the inner arrays of int ( allocates new memory if i >= oldSizeA )
for ( int i = 0; i < newSizeA; i ++ )
{
int *temp = NULL; // allocate new memory if i >= oldSizeA
if ( i < oldSizeA )
temp = array[i]; // reallocate array[i] if i < oldSizeA
temp = realloc( temp, newSizeB * sizeof( int ) );
assert( temp != NULL );
if ( temp == NULL )
return array;
array[i] = temp;
}
return array;
}
Use function reallocArray in your function create2darray to create your array. If the input paramter of ralloc is NULL, then new dynamic memory is allocated.
int **create2darray( int sizeA, int sizeB )
{
return reallocArray( NULL, 0, sizeA, sizeB );
}
First you have to free the inner arrays of int in a loop, then you have to free the array of pointers:
void free2DArray( int **array, int sizeA )
{
for (int i = 0; i < sizeA; i ++)
free( array[i] );
free( array );
}
int main( int argv, char *argc[] ){
int sizeA = 1;
int sizeB = 10;
int **testArray = create2darray( sizeA, sizeB );
for ( int i = 0; i < sizeB; i++ ) {
testArray[0][i] = 2;
}
int oldSizeA = sizeA;
int oldSizeB = sizeB;
sizeB = 2*sizeB;
testArray = reallocArray( testArray, oldSizeA, sizeA, sizeB );
for( int i = oldSizeB; i < sizeB; i++ ) {
testArray[0][i] = 3;
}
for( int i = 0; i < sizeB; i++ ) {
printf("%d", testArray[0][i]);
}
free2DArray(testArray, sizeA );
return 0;
}
In Free2DArray(), you free() the individual arrays of integers, but not the "outer" dimension of the array which holds the integer pointers.
You could add another call to free() after the loop to take care of that.
In main():
for(i = 0; i <size; i++) {
printf("%d", testArray[0][i]);
free2DArray(testArray, size);
}
you will end up free()-ing the (inner) integer arrays multiple times.
The call to free2DArray() should be outside the loop.

Strange output from Counting Sort in C

I have the following Counting Sort function
/*
*File: countingSort.c
*Description: A counting sort subroutine. Takes as input an array of integers.
* an array length and a range. All values in the input array must fall within [0, range].
* Takes O(range + arrayLen) time and O(range + arrayLen) extra space
*
*/
#include "countingSort.h"
int* countingSort(int unsorted[], int arrayLen, int range) {
int store[range + 1];
int sorted[arrayLen];
for ( int i = 0; i <= range; i++ ) {
store[i] = 0;
}
for ( int i = 0; i < arrayLen; i++ ) {
sorted[i] = 0;
}
for ( int j = 0; j < arrayLen; j++ ) {
store[unsorted[j]] ++;
}
for ( int i = 1; i <= range; i++ ) {
store[i] += store[i-1];
}
for( int j = arrayLen - 1; j >= 0; j-- ) {
sorted[store[unsorted[j]]] = unsorted[j];
store[unsorted[j]] --;
}
return sorted;
}
The function is giving me really strange output. The output is nothing like the input most of the times but sometimes it just works.
Why is this happening?
I am calling it from another file called cSortTest.c.
That file looks like this
/*
*File: cSortTest.c
*Description: Tests countingSort.c
*
*/
#include <stdio.h>
#include "countingSort.h"
int main() {
int data[8] = { 2, 1, 9, 4, 4, 56, 90, 3 };
int* p;
p = countingSort(data, 8, 90);
for ( int i = 0; i < 8; i++ ) {
printf("%d Element: %d\n", i, *(p+i) );
}
}
You are returning a local array variable. This variable is destroyed when the function exits, making the address to it no longer safe or valid to access. In fact accessing it will give you what is called undefined behavior, which explains why it sometimes appears to "work".
This is a classic beginner's mistake in C. You must either have the caller pass in the desired destination array, or use malloc() to allocate "persistent" heap memory and return that:
int* countingSort(int unsorted[], int arrayLen, int range) {
int *sorted = malloc(arrayLen * sizeof *sorted );
if (sorted== NULL)
return NULL;
/* rest of sorting */
return sorted;
}
The arrayLen * sizeof *sorted expression computes the number of bytes required for the allocation. There's no need to use calloc() which clears the memory; you're going to overwrite each element so clearing it is just wasted effort.

Getting runtime error when i access (table->array[i][i]).min = (table->array[i][i]).max = arr[i];

I am using DP to fill a table which contains maximum & minimum item from index i to index j in an array. Whether this approach is efficient or not, is not an issue to me.
Consider the below code snippet:
typedef struct Slot
{
int min;
int max;
}Slot;
typedef struct Table
{
Slot* *array;
int size;
}Table;
Table* createTable( int size )
{
Table* table = malloc( sizeof( Table ) );
if( !table )
return NULL;
table->array = ( Slot(*)[size] ) malloc( size * size * sizeof( Slot ) );
if( !(table->array) )
return NULL;
table->size = size;
return table;
}
void foo( int arr[], int size )
{
Table* table = createTable( size );
if( table == NULL )
{
printf( "Out of memory" );
return;
}
int i;
for( i = 0; i < size; ++i )
(table->array[i][i]).min = (table->array[i][i]).max = arr[i]; <----------
}
I am getting runtime error. When i comment the below two statements, it runs fine.
for( i = 0; i < size; ++i )
(table->array[i][i]).min = (table->array[i][i]).max = arr[i]; <----------
Why it is showing runtime error?
The malloc of your 2D array Slot is wrong:
table->array = ( Slot(*)[size] ) malloc( size * size * sizeof( Slot ) );
instead of this you should do this:
table->array = (Slot**) malloc(sizeof(Slot*));
for (int i = 0; i < ArraySizeX; i++)
table->array[i] = (Slot*) malloc(ArraySizeY*sizeof(Slot));
or if you wish to do it in one malloc call, however then only have a Slot* in your Table:
table->array = (Slot*) malloc(SizeX * SizeY * Sizeof(Slot));
This will allocate your double array properly.
Then also, this construct:
for( i = 0; i < size; ++i )
(table->array[i][i]).min = (table->array[i][i]).max = arr[i];
you should really do one assignment at a time:
for( i = 0; i < sizeX; ++i )
{
(table->array[i][i]).max = arr[i];
(table->array[i][i]).min = (table->array[i][i]).max;
}

Resources