How to reallocate memory for a 2D float array? - c

I tried the following to reallocate a 2D float array whose size chages from 2X2 to 3X3. The code throws a segfault while trying to realloc memory for weights[2].
num_vertices = 2;
float **weights = malloc(num_vertices*sizeof(float *)); // weight array matrix
for(i = 0; i < num_vertices; i++){
weights[i] = malloc(num_vertices*sizeof(float));
}
num_vertices = 3;
weights = realloc(weights, num_vertices*sizeof(float *)); // weight array matrix
for(i = 0; i < num_vertices; i++){
weights[i] = realloc(weights[i], num_vertices*sizeof(float));
}
Of course, I can free the 2D array and malloc again, but I was looking for a more elegant solution. Any ideas?

The problem is that weights[2] contains garbage after you realloc weights.
You probably want to do something like this:
new_vertices = 3;
weights = realloc(weights, new_vertices*sizeof(float *));
for(i = 0; i < new_vertices; i++)
{
if (i >= num_vertices)
weights[i] = NULL;
weights[i] = realloc(weights[i], new_vertices*sizeof(float));
}
num_vertices = new_vertices;
Note that you have a potential memory leak if realloc ever fails. Since you have no error checking yet though this probably doesn't matter for now.

The realloc of weights[2] is trying to realloc unallocated memory, since weights[2] was never assigned any pointer.
Usually, if you want a 2D array, just use wegihts[width*y + x] to index into the array, instead of making an array of pointers.

You can't loop to the new vertice count, as that part of the outer array is not allocated yet and contain uninitialized data. Instead loop to the new num_vertices - 1 and reallocate, then create a brand new weights[num_verticees - 1].

Related

Array size redefinition

So basically according to definition of array we cannot change array size. But if I am adding element to a same array by shifting other elements to the right of array, so the array size is going to increase.
How this is possible?
#include<stdio.h>
int main() {
int n, j, k, item;
printf("Enter size of array:\n");
scanf("%d", &n);
printf("Enter element to insert and position of element:\n");
scanf("%d,%d", &item, &k);
int a[n];
for (j = 0; j < n; j++) {
printf("Enter a[%d] element:\n", j);
scanf("%d", &a[j]);
}
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j];
j = j - 1;
}
a[k - 1] = item;
for (j = 0; j <= n; j++) {
printf("%d\n", a[j]);
}
}
Shifting the contents of the array to the right will not resize the array. If the array was not already large enough to hold the result of the shift, then you have overrun the array object, and have induced undefined behavior.
There is no way to dynamically increase the size of a variable with static or auto duration (e.g., global or local variables), and this includes arrays. If your compiler supports variable length arrays (VLAs), changing the value of the expression controlling the dimension of the array does not affect the array's size.
int main (void) {
int n = 3;
int v[n];
printf("%zu\n", sizeof(v));
++n;
printf("%zu\n", sizeof(v));
}
The program above will print the same value twice.
I am not entirely sure what you're asking, but for any readers interested in knowing how to dynamically change the size of an array in C: if an array is declared in stack memory, its size cannot change. However, a block of memory intended to be used as an array is declared on the heap (i.e. with malloc or calloc), can be reallocated with a different size if necessary:
int *data = malloc(10 * sizeof(int)), *data2 = NULL;
int i;
if(data == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++)
{
data[i] = i;
}
data2 = realloc(data, 11 * sizeof(int));
if(data2 == NULL)
{
free(data);
perror("realloc");
exit(EXIT_FAILURE);
}
else
{
data = data2;
}
data[10] = 10;
for (i = 0; i < 11; i++)
printf("%d ", data[i]);
free(data);
data = NULL;
Shifting elements in an array down one element will not change its size.
If you declare an array as
T a[N]; // assume N is a constant expression
then a can only ever hold N elements of type T - no more, no less. You cannot add extra elements to the array, nor can you remove elements from the array.
However...
C does not force any bounds checking on array subscripting, so it's possible that you can read or write past the end of the array such as
a[N + 2] = x;
The behavior on doing so is undefined - your program may work as expected, or it may crash immediately, or you may corrupt other objects in the program. The runtime environment will (most likely) not throw an IndexOutOfBounds-type exception.
There is a thing called a variable-length array that was added in C99, where the array size is not a constant expression:
size_t size = some_value();
T a[size];
Variable length arrays are only variable length in the sense that their size isn't determined until runtime - however, once defined, their size is fixed throughout their lifetime, and like regular arrays, they cannot grow as new items are added.
If you dynamically allocate a chunk of memory using
T *a = malloc( sizeof *a * some_size );
then you can grow or shrink that chunk of memory using realloc:
T *tmp = realloc( a, sizeof *a * (some_size * 2) );
if ( tmp )
{
a = tmp;
some_size *= 2;
}
.... array we cannot change .. But if I (do something special) ... the array size is going to increase.
How this is possible?
Undefined behavior
Arrays cannot change size once defined.
Code attempts to assign a[j + 1] with j = n-1 and that is a[n]. This is outside array a[] and so undefined behavior. Rest of code is irrelevant for at that point anything is possible, code crash, error report, even apparent successful array expansion, etc.
int a[n];
...
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j]; // To attempt access to `a[n]` is UB

Array overwritten after dynamic memory allocation in C

I'm writing a program that converts an array of integer vectors to an adjacency matrix , an (n+1)x(n+1) array. When in the function i have written to do this the dynamic memory allocation from setting up the int** seems to overwrite the n+1 and n+n elements of the integer vector.
int** makeAdjMatrix(IntVec* Vec, int length) { //allocates a new nxn array
printf(" madm test %d \n" , Vec[1]->data[6]);
//confirming that the intvec entered okay
int** new;
new = (int**)malloc(length+1*length+1*sizeof(int*))
printf(" madm test %d \n" , Vec[1]->data[6]);
// confirming that something happenend to the intvec
for (int i = 0; i <= length + 1; i++) {
new[i] = (int*)malloc(length + 1*sizeof(int));
}
for (int i = 1; i <= length+1; i++) {
for (int j = 1; j <= length+1; j++) {
new[i][j] = 0;
}
}
outputs normally for all elements in the vector data structure except those n+1 and above. n in this case being 5.
the above code prints
test 1
test 33
segfault
(because there is no 33rd indices in the array which the code referrences later)
is this memory exhaustion? how am I overwriting a previously allocated array on the heap? this might be a bit vague, this is my first question go easy on me. by the way this only happens when the vector array has repeated identical input.
how bad did I mess up?

Free() from 2 dimensional array

I'm trying to free mem from 2 dimensional array the same way like in this: [C: Correctly freeing memory of a multi-dimensional array
//initialization
int **tab;
int i,j;
int x_max=5,y_max=7;
tab = calloc(x_max+1, sizeof(int));
for(j = 0; j <=x_max+1; j++)
{
tab[j] = calloc(y_max+2, sizeof(int));
}
and than:
for (i = 0; i <=x_max+1; i++)
{
free(tab[i]);
}
free(tab);
This seems to be like in the example in above link, but my program keeps crashing (when I comment freeing mem part everything works good.) Also when I try to debug program line by line everything works. (Debugger finished with status 0)
First of all, it's not a 2D array. It's a jagged array.
Your initial allocation is problematic. You want to allocate x_max+1 pointers, not ints. And you are accessing outside of the bounds since you allocated x_max+1 pointers, yet access upto x_max+2 pointers.
It's usually preferred to use the thing itself to allocate memory such as:
tab = calloc(x_max+1, sizeof *tab);
so that you don't need to worry about the type being changed later.
tab = calloc(x_max+1, sizeof(int));
for(j = 0; j <=x_max+1; j++)
{
tab[j] = calloc(y_max+2, sizeof(int));
}
should be
tab = calloc(x_max+1, sizeof *tab); /* equivalent to: tab = calloc(x_max+1, sizeof(int*)); */
for(j = 0; j < x_max+1; j++)
{
tab[j] = calloc(y_max+2, sizeof(int));
}
You should also check the return value of calloc() for failures.

GNU buffer overflow using malloc

I am running in a loop the following function:
int* rpermute(int n)
{
int* a = malloc(n * sizeof(int));
int k;
for (k = 0; k < n; k++)
{
a[k] = k;
}
for (k = n - 1; k > 0; k--)
{
int j = rand() % (k + 1);
int temp = a[j];
a[j] = a[k];
a[k] = temp;
}
return a;
}
If I set a new int variable in my code every variable is changing, I assume it is a buffer overflow problem.
Running the valgrind i get the following:
==4459== 73,036 bytes in 19 blocks are definitely lost in loss record 1 of 1
==4459== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4459== by 0x402CFB: rpermute (in /home/giwrgos/Desktop/crowdv22/crowd_evacuation)
==4459== by 0x403378: main (in /home/giwrgos/Desktop/crowdv22/crowd_evacuation)
I use linux through the virtualbox but I have set enough storage and ram, what should I do?
EDIT: See poster's comment below, the problem is not in this code after all.
You should simply free() the memory allocated in and returned by rpermute(). This must be done in the code from where you call rpermute(), once you're done with this array.
I understand that you regenerate this array for differing int values (the n parameter of rpermute()). Perhaps you simply assign a new output to the array you keep:
int* array;
...
array = rpermute(100);
// Some time later.
array = rpermute(200); // Previous array memory is leaking.
You should do instead:
free(array);
array = rpermute(200);
Note that this is not a 'buffer over flow', but a memory leak instead. I checked you code for buffer overflow: index of a points outside it, but this seemed to be ok in both loops.

How to insert an element into an array on malloc?

say we are going to insert an element into an array on malloc. I know where and how to insert, but I'm having trouble shuffling every succeeding element down by 1. What would be the technical approach for this? Thanks
| x x x x x x x x x x x | original array
| x x x x x 0 x x x x x x | new array
Suppose the "memmove" function is not available to us...
Yes, if you need to do this without memmove, you can do it with a simple loop. Note that you might also need to use realloc first, to expand the size of the allocated array so that it can fit the new element.
The trick to this is having the loop move each element one forward, starting from the last one. A moment's reflection should tell you why this is necessary.
The basic principle is the same whether the array is dynamically allocated, statically allocated or automatically allocated. The main difference is that if there is insufficient room in a dynamically allocated array, you can reallocate it with more space (subject to some system-imposed limits. Assuming there is enough space in the array, you could use memmove() to copy the section of the array after target location up one space, and then set the target location to the inserted value. Or you could write a loop to do the job.
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
Now insert at position n = 2:
memmove(&dynarr[n+1], &dynarr[n], (idx - n) * sizeof(int));
dynarr[n] = 19;
idx++;
That's a bulk move, an assignment, and increment the counter because there's one more element in the array.
Since the question was edited to disallow memmove(), here is a solution with simple array indexing, assuming that the same initialization sequence is used:
int i;
int n = 2;
for (i = idx; i > n; i--)
{
dynarr[i] = dynarr[i-1];
}
dynarr[n] = 19;
idx++;
Complete example code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void print_array(int *a, int n)
{
int i;
for (i = 0; i < n; i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
}
int main()
{
{
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
printf("Before insert\n");
print_array(dynarr, idx);
int n = 2;
memmove(&dynarr[n+1], &dynarr[n], (idx - n) * sizeof(int));
dynarr[n] = 19;
idx++;
printf("After insert\n");
print_array(dynarr, idx);
free(dynarr);
}
{
int *dynarr = malloc(24 * sizeof(*dynarr));
int idx = 0;
dynarr[idx++] = 0;
dynarr[idx++] = 23;
dynarr[idx++] = 34;
dynarr[idx++] = 9;
dynarr[idx++] = 15;
printf("Before insert\n");
print_array(dynarr, idx);
int n = 2;
int i;
for (i = idx; i > n; i--)
{
dynarr[i] = dynarr[i-1];
}
dynarr[n] = 19;
idx++;
printf("After insert\n");
print_array(dynarr, idx);
free(dynarr);
}
return(0);
}
As Don suggested, memmove() will allow moving part of this array, in order to make room for the new element.
Depending on the size of the elements in the array, you may also consider storing only pointers, in the array, allowing easier/faster re-shuffling of the array, at the cost of a extra indirection when accessing individual elements. (and also at the cost of having to manage individual element-sized memory blocks). Deciding on this type of approach depends on the amount of reorganization of the array elements, as well as their size.
Alert: in view of the added "picture" in the question, memmove(), or indeed any operation, may be impossible, if the memory move implies writing past the size of memory originally allocated!
If this is really what is desired, the idea of an array of pointers may be more appropriate as this allows allocating an over-sized memory block initially (for the array proper) and to allocate (or dispose of) individual elements as needed.
Edit: "We're not allowed to use memmove()" indicates some form of homework. (BTW do tag it as such !!!)
To better help you we need to understand the particular premise of the question. Here's what appears to be the situtation:
1) we readily have an array, containing say N elements.
2) the array on the heap, i.e. it was allocated using malloc() (or related
functions)
3) the effective size of the malloc-ated block of memory is bigger than that of
the array.
Is #3 true ?
4) Depending on #3 we need to either allocate a new memory block (a bigger one)
and copy the array. We expect this copy would be done in 3 steps
- copy the elements that precede the new element
- copy the new element
- copy the elements that are after the new element
or... (if we have enough room), we'd require two steps
- "shift" the elements that are supposed to be after the new element
This can be done one element at a time, if we wish to avoid memcopy
- copy the new element.

Resources