I have a function which is called several times, with a parameter n which defines the n*2-sized 2d array:
void myfunc(int n){
static int n0=0,i;
static double **x=NULL;
if(n>n0){ //realloc if n grows
x=(double **)realloc(x,n*sizeof(double*)));
for(i=0;i<n;i++){
x[i]=(double *)realloc(x[i],2*sizeof(double))); // <--problem here
}
n0=n;
}
}
At the first call the **x is initialized to NULL, but x[i] are not, and thus the second realloc may behave not correctly.
Is there a way to realloc the rows of an empty 2d matrix, without first using malloc or calloc?
Here, you should be using malloc() instead of realloc() since you are not re-allocating memory here.
But if your code can't know if the data is new, it should first be initialized to NULL in order for realloc() to work.
I would change the function to use malloc the first time and realloc after that.
However, there is no need to realloc for the current elements of x. You only need to use malloc for the new elements of x.
void myfunc(int n)
{
static int n0 = 0;
static double **x = NULL;
if ( n > n0)
{
if ( x == NULL )
{
// Use malloc to get memory for x
x = malloc(n*sizeof(double*));
for( int i = 0; i < n; i++)
{
x[i] = malloc(2*sizeof(double));
}
}
else
{
// Use realloc to get more memory for x.
x = realloc(x, n*sizeof(double*));
// Allocate memory only for the new elements of x.
for( int i = n0; i < n; i++)
{
x[i] = malloc(2*sizeof(double));
}
}
n0 = n;
}
}
PS Don't cast the return value of malloc or realloc. See Specifically, what's dangerous about casting the result of malloc? to understand why.
After a little bit of thought, I realized the function can be simplified a bit.
void myfunc(int n)
{
static int n0 = 0;
static double **x = NULL;
if ( n > n0)
{
if ( x == NULL )
{
// Use malloc
x = malloc(n*sizeof(double*));
}
else
{
// Use realloc
x = realloc(x, n*sizeof(double*));
}
// Use malloc for the new elements of x.
// When n0 is 0, it will be all of them.
for( int i = n0; i < n; i++)
{
x[i] = malloc(2*sizeof(double));
}
n0 = n;
}
}
void myfunc(int n){
static int n0=0,i;
static double **x=NULL;
if(n>n0){
x=realloc(x,n*sizeof(double*)));
for(i=n0;i<n;i++){
x[i]=malloc(2*sizeof(double)));
}
n0=n;
}
}
In addition to various answer detailing how to increase the allocation, code could be altered to allow an eventual freeing of the allocation by calling with myfunc(0).
Also better to use size_t for array sizing.
No need for i to be static.
This function hides its result, perhaps return the pointer?
double **myfunc(size_t n) {
static size_t n0 = 0;
static double **x = NULL;
if (n > n0) {
void *new_ptr = realloc(x, sizeof *x * n);
if (new_ptr == NULL) {
TBD_Code(); // Handle out-of-memory
}
x = new_ptr;
for (size_t i = n0; i < n; i++) {
x[i] = malloc(sizeof *(x[i]) * 2);
}
n0 = n;
} else if (n == 0) {
while (n0 > 0) [
free(x[--n0]);
}
free(x);
x = NULL;
}
return x;
}
Consider ptr = malloc(sizeof *ptr * n); style of using *alloc(). It is easier to code right, review and maintain than ptr = malloc(sizeof (de-referenced_ptr_type) * n);
Related
int* dynamicArray(int n, int queries_rows, int queries_columns, int** queries, int* result_count) {
int i,j;
int lastAnswer = 0,y,resultCount = 0;
int *result = NULL;
int **seqList = (int**) calloc (n,sizeof(int*));
for (i=0; i<queries_rows;i++)
{
y = (queries[i][1] ^ lastAnswer)% n;
if(queries[i][0] == 1){
if(seqList[y]==NULL){
int *dummy = (int*) calloc (2,sizeof(int));
seqList[y]=dummy;
}
for(j=0;j<n;j++){
if(seqList[y][j])
continue;
else {
printf("%d %d entry %d",y,j,seqList[y][j]);
seqList[y][j] = queries[i][2];
}
}
}
if(queries[i][0] == 2){
lastAnswer = seqList[y][queries[i][2]];
resultCount++;
if(result == NULL)
result = (int*) calloc (1,sizeof(int));
else {
result = (int*) realloc (result,resultCount * sizeof(int));
}
result[resultCount - 1] = lastAnswer;
}
}
*result_count = resultCount;
return result;
}
Anything wrong with the above realloc usage for giving out a "segfault"?
Is this the right way to use realloc?
Also running a debugger is not possible as this is a function completion of cooding site?
You are missing a few spots to "derive" a pointer to do any sort of action with the value...so you're probably trying to allocate/reallocate dynamic memory with the integers memory address instead of the value of the pointer(which would be deriving it).
Try putting an asterisk in front of the pointer variables when allocating/reallocating the memory.
Note these lines
int **seqList = (int**) calloc (n,sizeof(int*));
for (i=0; i<queries_rows;i++)
{
y = (queries[i][1] ^ lastAnswer)% n; // <-- ?
if(queries[i][0] == 1) {
if(seqList[y]==NULL) {
int *dummy = (int*) calloc (2, sizeof(int));
// ^^^
seqList[y]=dummy;
// ^^^
}
for( j = 0; j < n; j++ ) {
// ^^^^^ is n bigger than 2?
if( seqList[y][j] )
// ^^^
continue;
else {
// ...
seqList[y][j] = queries[i][2];
// ^^^
}
}
}
According to what the OP commented "n will be till 10^5", but only enough memory to store a couple of ints has been allocated.
Also note that both calloc and realloc may fail, but none of the values returned by those functions are checked.
Further references to address other issues
Do I cast the result of malloc?
calloc with structure with pointers
Proper usage of realloc
this is quite basic but I've been trying to solve it for a few hours now with no success. This code is supposed to read 3 ints from user input and then, points according to the ints (n = how many, d = dimension, k is unrelated to this part) and create an array of them. For some reason it crashes on the second loop, where it fails to create the second point, but im not sure why. I think it might has something to do with malloc but I'm totally lost, would appreciate any help.
I inserted the input :
5 3 2
1.2 3.4 0.1
2 times before it crashed.
Code is below:
int main(){
double* pdata;
int n,d,k;
scanf("%d %d %d",&n,&d,&k );
SPPoint* parr [n];
for(int i=0; i<n; i++)
{
double darr [d];
for(int j = 0; j < d-1; j++)
{
scanf(" %lf", &darr[j]);
}
scanf(" %lf", &darr[d-1]);
pdata = darr;
parr[i] = spPointCreate(pdata, d, i);
}
}
This is the code for the spPointCreate function:
struct sp_point_t{
double* data;
int dim;
int index;
};
SPPoint* spPointCreate(double* data, int dim, int index){
SPPoint* point = malloc(sizeof(SPPoint*));
if(point == NULL)
{
return NULL;
}
point->data = (double*) malloc(sizeof(data));
for( int i=0 ; i<dim ; i++)
{
point->data[i] = data[i];
}
point->dim = dim;
point->index = index;
return point;
}
SPPoint* point = malloc(sizeof(SPPoint*));
should be: struct SPPoint* point = malloc(sizeof(*point));
point->data = (double*) malloc(sizeof(data));
should be point->data = malloc(dim * sizeof(*point->data));
since you want to allocate dim doubles for your point.
Code is mis-allocating in 2 places
// Bad
SPPoint* spPointCreate(double* data, int dim, int index){
SPPoint* point = malloc(sizeof(SPPoint*)); // allocate the size of a pointer
...
point->data = (double*) malloc(sizeof(data)); // allocate the size of a pointer
Instead avoid mis-coding the type and allocate to the the size of the de-referenced variable.
Also need to allocate N objects.
SPPoint* spPointCreate(double* data, int dim, int index){
size_t N = 1;
SPPoint* point = malloc(sizeof *point * N);// allocate the size of `*point` * N
...
assert(dim >= 0);
N = dim;
point->data = malloc(sizeof *(point->data) * N);
BTW, casting the result of malloc() not needed.
2nd allocation would benefit with a NULL check. More complicated as dim may be 0 and a malloc() return of NULL in that case is OK.
N = dim;
point->data = malloc(sizeof *(point->data) * N);
if (point->data == NULL && N > 0) {
free(point);
return NULL;
}
I need to create a dynamic array and put five number, after there is another input which is how much I have to increase the array size.
When all input are ended I am going to increase the array size and put numbers inside.
everything works but free return me this error: "free(): invalid next size (fast): 0x00000..."
I think there are errors inside "extend" function
void extend(int *V, int n, int s)
{
int *pt;
pt = realloc(V, n*sizeof(int));
int i;
pt[5]=s;
for(i=6;i<(5+n);i++)
pt[i] = pt[i-1]*2;
}
int main()
{
int *v;
int n,i, sum;
sum = 0;
v = malloc(sizeof(int)*5);
for(i=0;i<5;i++)
{
scanf("%d", &v[i]);
sum+=v[i];
}
scanf("%d", &n);
extend(v,n,sum);
for(i=0;i<(5+n);i++)
printf("%d\n", v[i]);
free(v);
return 0;
}
The function does not change the original variable v. It should be defined at least like
void extend(int **V, int n, int s)
{
int *pt;
pt = realloc(*V, n*sizeof(int));
if ( pt )
{
int i;
pt[5]=s;
for(i=6; i < n; i++)
pt[i] = pt[i-1]*2;
*V = pt;
}
}
Or
int extend(int **V, int n, int s)
{
int *pt;
pt = realloc(*V, n*sizeof(int));
int success = pt != NULL;
if ( success )
{
int i;
pt[5]=s;
for(i=6; i < n; i++)
pt[i] = pt[i-1]*2;
*V = pt;
}
return success;
}
And the function should be called lije
extend( &v,n,sum);
Take into account that the function is unsafe because in general n can be less than or equal to 5. And this statement
for(i=6;i<(5+n);i++)
^^^^
can result in undefined behavior.
Or the function shall allocate n + 5 elements. For example
pt = realloc(*V, ( n + 5 )*sizeof(int));
^^^^^^^^
Also the using of this magic number 5 is unclear and does not make sense.
Well, in function extend:
You are allocating pt to a memory block of n entries
You are attempting to access pt at indexes beyond n-1
More specifically, with:
pt = realloc(V, n*sizeof(int));
for (i=6; i<(5+n); i++)
pt[i] = ...
You are performing illegal memory-access operations on:
pt[n]
pt[n+1]
pt[n+2]
pt[n+3]
pt[n+4]
The realloc returns a pointer to the new memory block but you do not return that to the caller. Instead v in main, is the same v that was before the call but now invalid and which causes your error no doubt, easiest is to return pt instead:
int* extend(int *V, int n, int s)
{
int *pt;
pt = realloc(V, n*sizeof(int));
int i;
pt[5]=s;
for(i=6;i<(5+n);i++)
pt[i] = pt[i-1]*2;
return pt;
}
...
v = extend(v,n,sum);
another thing that is not correct is your initialization of the new elements, n should contain the number of new elements plus any old since you want the allocated the block to be bigger. better to give old and new number of elements to it:
int* extend(int *V, int oldNumber, int newNumber, int s)
{
int *pt = realloc(V, newNumber*sizeof(int));
int i;
if (pt==NULL)
{
fprintf(stderr,"Out of memory\n");
return V;
}
pt[oldNumber]=s;
// now you can initialize the rest of the array
for(i=oldNumber+1;i<newNumber;i++)
pt[i] = pt[i-1]*2;
return pt;
}
...
v = extend(v,5,n,sum);
Grow an array like this
int capacity = 10; // don't start off as tiny
ENTRY *array = malloc(capacity * sizeof(ENTRY));
int N = 0; //number of entries.
To add
int addentry(ENTRY *entry)
{
ENTRY *temp;
if(N >= capacity)
{
temp = realloc(array, (capacity + capacity/2) * sizeof(ENTRY));
if(!temp)
goto out_of_memory;
array = temp;
capacity = capacity + capacity/2;
}
array[N] = *entry;
N++;
return 0;
out_of_memory:
//always a problem, maybe terminate program here
// as it is, just shunt up
return -1;
}
You need the temp because realloc returns 0 on failure but keeps
the argument intact, so you need to keep array to destroy it
gracefully. Grow by about 1.5, doubling is too aggressive and
reallocating on every call is too expensive.
As a homework, I'm supposed to create 2 functions that enable you to push and pop elements to an array that acts as a queue. We're supposed to do this dynamically allocating memory. My program is almost working, but sometimes when adding and removing too many elements, I get errors like "realloc(): invalid next size", double free (when I've only called the free function once) and some of the elements in the beginning of the queue are set to 0. For instance, if I first add 100 elements, then remove 90 and try to add another 20, I get "free(): invalid next size (fast): 0x0000000001ea6010".
What am I doing wrong here?
According to suggestions below I changed my functions to take a double pointer as an input for the array. That, however, now gives me a Segmentation fault - which means now I don't know what to look for at all...
#include <stdio.h>
#include <stdlib.h>
void enqueue(int **arr, int* lastElementIdx, size_t* totalElements, int element) {
if (*lastElementIdx >= *totalElements) { // check if memorry is sufficient, otherwise double
*totalElements *= 2;
int* temp = realloc(arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // just in case realloc fails
printf("Allocation error\n");
} else {
*arr = temp;
}
}
if (*lastElementIdx <= *totalElements) {
*lastElementIdx += 1; // once everything is done: add element
*arr[*lastElementIdx] = element;
}
}
int dequeue(int **arr, int* lastElementIdx, size_t* totalElements) {
if (*lastElementIdx > -1) { // if queue is not empty...
int deleted = *arr[0]; // save deleted value first (in case it's still needed)
for (int i = 0; i <= *lastElementIdx; i++) { // shift all elements
*arr[i] = *arr[i + 1];
}
*lastElementIdx -= 1; // index is now decreased by 1
if (((*totalElements / 2) >= 10) && ((*lastElementIdx + 1) < (*totalElements / 2))) { // cut memory in half if not needed
*totalElements /= 2;
*arr = realloc(arr, (*totalElements * sizeof(int)));
int* temp = realloc(arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // in case realloc fails
printf("Allocation error\n");
return 0;
} else {
*arr = temp;
}
}
return deleted;
} else { // if queue is empty, print that there's nothing to dequeue
printf("There are no elements inside the queue\n");
return 0;
}
}
void printQueue(int arr[], int lastElementIdx) {
for (int i = 0; i <= lastElementIdx; i++) { // print entire queue
printf("[%d] = %d\n", i, arr[i]);
}
printf("\n");
}
int main (void) {
size_t totalElements = 10; // number of needed elements at the time
int lastElementIdx = -1; // index of last element in queue at the time
int *arr = calloc(totalElements, sizeof(int));
int **arrpointer = &arr;
for (int i = 1; i < 101; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
for (int i = 0; i < 90; i++) {
dequeue(arrpointer, &lastElementIdx, &totalElements);
}
printQueue(arr, lastElementIdx);
for (int i = 1; i < 21; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
free(arr);
return EXIT_SUCCESS;
}
When you expand or contract the storage for your queue, you need to provide a pointer to the storage back to the caller. This is because realloc() does not necessarily resize a memory block in-place -- it may create a new, differently sized block elsewhere. It is permitted to do so even when it resizes to a smaller block, not only when it resizes to a larger one.
Your usage of variable temp gives the appearance that you are aware of this issue, but as #DerkHermann first observed, you mishandle the resulting pointer. Perhaps you meant to write something along the lines of
arr = temp;
instead. Even that is not sufficient, however. C has only pass-by-value, so if you modify the value of function parameter arr, that modification is visible only in the function (which receives in arr a copy of the value the caller passes). In the event that realloc() allocates a new block, that leaves the caller with an invalid pointer.
If you want your enqueue() and dequeue() functions to be able to resize the storage for the queue, then you must pass the pointer to that storage indirectly. The most straightforward way of doing that, given where you are now, would be to pass a double pointer, so that you can modify its referrent:
void enqueue(int **arr, int* lastElementIdx, size_t* totalElements, int element) {
/* ... */
*arr = temp;
/* ... */
}
Observe, however, that you are passing three separate pointers that among them represent the state of the queue. It would be cleaner to create a struct type that combines those details in one package, and to pass a pointer to an object of that type:
struct queue {
int *arr;
size_t capacity;
size_t last_element_index;
};
void enqueue(struct queue *queue, int element) {
/* ... */
queue->arr = temp;
/* ... */
}
Maybe it's not the only problem, but at least the following line does not what you seem to expect:
*temp = *arr;
It looks as if you want to replace arr with the result of the realloc, delivering it back to the calling function (as with your other inout arguments). But, arr is not an inout argument: It is an array of integers, not a pointer to an array of integers. What you are actually doing with your above line of code is to copy the first element of arr to the newly allocated memory range. That newly allocated memory range temp, then, is nevertheless forgotten, creating a memory leak.
Adding a double pointer to reallocate the space in the right places, changing the comparing function with size_t totalElements and fixing a few additional mistakes finally did the trick.
#include <stdio.h>
#include <stdlib.h>
void enqueue(int **arr, int* lastElementIdx, size_t* totalElements, int element) {
if (*lastElementIdx + 1 >= (int)(*totalElements) - 1) { // check if memorry is sufficient, otherwise double
*totalElements *= 2;
int* temp = realloc(*arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // just in case realloc fails
printf("Allocation error\n");
} else {
*arr = temp;
}
}
if (*lastElementIdx + 1 <= (int)(*totalElements) - 1) {
*lastElementIdx += 1; // once everything is done and if there is now enough space: add element
(*arr)[*lastElementIdx] = element;
}
}
int dequeue(int **arr, int* lastElementIdx, size_t* totalElements) {
if (*lastElementIdx > -1) { // if queue is not empty...
int deleted = (*arr)[0]; // save deleted value first (in case it's still needed)
for (int i = 0; i <= *lastElementIdx; i++) { // shift all elements
(*arr)[i] = (*arr)[i + 1];
}
*lastElementIdx -= 1; // index is now decreased by 1
if (((*totalElements / 2) >= 10) && ((*lastElementIdx + 1) < (*totalElements / 2))) { // cut memory in half if not needed
*totalElements /= 2;
int* temp = realloc(*arr, (*totalElements * sizeof(int)));
if (temp == NULL) { // in case realloc fails
printf("Allocation error\n");
return 0;
} else {
*arr = temp;
}
}
return deleted;
} else { // if queue is empty, print that there's nothing to dequeue
printf("There are no elements inside the queue\n");
return 0;
}
}
void printQueue(int arr[], int lastElementIdx) {
for (int i = 0; i <= lastElementIdx; i++) { // print entire queue
printf("[%d] = %d\n", i, arr[i]);
}
printf("\n");
}
int main (void) {
size_t totalElements = 10; // number of needed elements at the time
int lastElementIdx = -1; // index of last element in queue at the time
int *arr = calloc(totalElements, sizeof(int));
int **arrpointer = &arr;
for (int i = 1; i < 101; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
for (int i = 0; i < 102; i++) {
dequeue(arrpointer, &lastElementIdx, &totalElements);
}
printQueue(arr, lastElementIdx);
for (int i = 1; i < 21; i++) {
enqueue(arrpointer, &lastElementIdx, &totalElements, i);
}
printQueue(arr, lastElementIdx);
free(arr);
return EXIT_SUCCESS;
}
I want to write a function in C language which returns the 2 dimension array to my main function.
A function that returns a dynamically allocated two dimensional array for the int type.
int ** myfunc(size_t width, size_t height)
{
return malloc(width * height * sizeof(int));
}
It has to be deleted with free once it is not used anymore.
EDIT This only allocates the space for the array which could be accessed by pointer arithmetic but unfortunately not by the index operators like array[x][y].
If you want something like this here is a good explanation. It boils down to something like this:
int ** myfunc(size_t ncolumns, size_t nrows)
{
int **array;
array = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
}
}
You can not simply return malloc( x * y * sizeof(type) );
This will produce a segmentation fault when you try to index the array as a 2 dimensional array.
int **a = malloc(10 * 10 * sizeof(int));
a[1][0] = 123;
a[0][1] = 321;
The result of the above: Segmentation fault
You need to first create an array of pointers with c/malloc() then iterate this array of pointers and allocate space for the width for each of them.
void *calloc2d(size_t x, size_t y, size_t elem_size) {
void **p = calloc(y, sizeof(void*));
if(!p) return NULL;
for(int i = 0; i < y; i++) {
p[i] = calloc(x, elem_size);
if(!p[i]) {
free2d(y, p);
return NULL;
}
}
return (void*)p;
}
And free
void free2d(size_t y, void *matrix) {
if(!matrix) return;
void **m = matrix;
for(int i = 0; i < y; i++) {
if(m[i]) free(m[i]);
}
free(m);
return;
}
It should be simple i guess...
char **functioName(char param[][20])
{
char[][20] temp = malloc(20 * 20 * sizeof char);
//processing
return temp
}
If you know the size of the array, you can do so:
int (*myfunc())[10] {
int (*ret)[10]=malloc(10*10*sizeof(int));
return ret;
}
This function return pointer to 10 arrays of 10 ints.
Of course, you should use it as it is, and don't forget to free it after using.