Freeing dynamic 2D array not working as expected in C - c

When I run code like the following:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int i, count = 0x09;
int sizei = 5, sizej = 2;
int **ary = malloc (sizei * sizeof **ary);
for (i = 0; i < sizei; i++) {
*(ary + i) = malloc (sizej * sizeof *(ary + i));
**(ary + i) = ++count;
printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
}
puts("----");
for (i = sizei - 1; i >= 0; i--) {
printf (" %2d |%p| +%x+ \n", i, (ary + i), *(*(ary + i)));
free (*(ary + i));
}
puts("----");
free (ary);
return 0;
}
I would expect that the first half would create a 2d dynamic array of ints called ary (i.e a pointer to a dynamically allocated array of pointers, each pointing to a dynamically allocated array of ints). The 0th element of each array **(ary + i) would then be recursively assigned the current value of count.
The second half would iterate in reverse, freeing each element of ary in the reverse it was malloc'd, followed by freeing ary itself.
This appears to work fine until I try to free *(ary + 0), at which point I get a double free / corruption error. I've included the output.
0 |0x1d6f010| +a+
1 |0x1d6f018| +b+
2 |0x1d6f020| +c+
3 |0x1d6f028| +d+
4 |0x1d6f030| +e+
----
4 |0x1d6f030| +e+
3 |0x1d6f028| +d+
2 |0x1d6f020| +c+
1 |0x1d6f018| +b+
0 |0x1d6f010| +1d6f0b0+
*** Error in `./a.out': double free or corruption (out): 0x0000000001d6f030 ***
I'm curious why the 0th element of the 0th element of ary (i.e *(*(ary + 0) + 0)) or just **ary) became what looks like some memory address (only slighly) out of bounds from what's taken up by this 2d array once it got out of the first loop.
And if I get rid of the second loop and just try to free ary directly without first freeing any of its elements I get something like:
0 |0x1d6f010| +a+
1 |0x1d6f018| +b+
2 |0x1d6f020| +c+
3 |0x1d6f028| +d+
4 |0x1d6f030| +e+
----
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000001d6f010 ***
I don't understand what I've done wrong here. Would using array notation make a difference? I need any solutions to allow me to have a dynamic length of each array independant of the length of the rest of the elements of ary if at all possible. The number elements of ary wouldn't necesarily be known at compile time either. I'm using gcc 4.9 if that's relevant.

Problem 1
int **ary = malloc (sizei * sizeof **ary);
is equivalent to
int **ary = malloc (sizei * sizeof int);
If sizeof a pointer is less than sizeof(int) in your system, you end up accessing memory out of bounds.
You need to use:
int **ary = malloc (sizei * sizeof *ary);
or
int **ary = malloc (sizei * sizeof(int*));
Problem 2
*(ary + i) = malloc (sizej * sizeof *(ary + i));
needs to be
*(ary + i) = malloc (sizej * sizeof **(ary + i));
or
*(ary + i) = malloc (sizej * sizeof int);
or
ary[i] = malloc (sizej * sizeof *ary[i]);
or
ary[i] = malloc (sizej * sizeof int);

ari is pointer a to array of pointer, so size of elements are pointers. In your code, you use sizeof **ary which is an int
int **ary = malloc (sizei * sizeof **ary);
For each of the pointer to array of int elements. In your malloc for those pointers, you use sizeof *(ary+i) which is a pointer to int
*(ary + i) = malloc (sizej * sizeof *(ary + i));
sizeof(int) is not always the same as sizeof(int*). In fact, on most 64 bits systems, which I suspect is what you use, sizeof(int)==4 and sizeof(int*)==8.
My guess is that you are using such a system, and because of that, you do not allocate enough memory for the main ari pointer and you are overflowing it with values, thrashing the content of critical memory management data so future malloc() and free() call have a big chance of failing completely.

Related

Why add one more block of memory after dynamic memory allocation using realloc()?

The Sorting Array of Strings problem on Hackerrank has a loop to take input in a 2D array of strings. This loop dynamically allocates memory for each string with malloc(), takes input with scanf() and then reallocates the block with one more block.
int n;
scanf("%d", &n);
char** arr;
arr = (char**)malloc(n * sizeof(char*));
for(int i = 0; i < n; i++){
*(arr + i) = malloc(1024 * sizeof(char));
scanf("%s", *(arr + i));
*(arr + i) = realloc(*(arr + i), strlen(*(arr + i)) + 1);
}
link: https://www.hackerrank.com/challenges/sorting-array-of-strings/problem
I have two questions:
Why is that extra block of memory used for?
Why is it using scanf() to take a string input and not fgets()? Isn't it a good practice?
*(arr + i) = malloc(1024 * sizeof(char));
It's allocating 1024 chars for the i-th string because the max string length is known
*(arr + i) = realloc(*(arr + i), strlen(*(arr + i)) + 1);
while here it's resizing the block to fit exactly the size of the string i
Since a single word is provided in input scanf will suffice

Int Array initialization after malloc

I got this little question about this int array initialization after I did memory allocation. I got below error:
"Line 7 Error: expected expression before '{' token"
This is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int *x=malloc(3*sizeof(int)); //allocation
*x={1,2,3}; //(Line 7) trying to initialize. Also tried with x[]={1,2,3}.
for(i=0;i<3;i++)
{
printf("%d ",x[i]);
}
return 0;
}
Is there any other way to initialize my array after I do memory allocation?
First of all, we must understand that the memory for array is allocated at heap memory area. Therefore we can initialize by following methods.
using memcpy function
pointer arithmetic
Above two methods preserve the memory allocation through malloc function.
But assignment through (int[]) {1,2,3} will cause memory wastage due to previous allocated heap memory.
int* x = (int*) malloc(3 * sizeof(int));
printf("memory location x : %p\n",x);
// 1. using memcpy function
memcpy(x, (int []) {1,2,3}, 3 * sizeof(int) );
printf("memory location x : %p\n",x);
// 2. pointer arithmetic
*(x + 0) = 1;
*(x + 1) = 2;
*(x + 2) = 3;
printf("memory location x : %p\n",x);
// 3. assignment, useless in case of previous memory allocation
x = (int []) { 1, 2, 3 };
printf("memory location x : %p\n",x);

Decreasing realloc [duplicate]

This question already has answers here:
Using realloc to shrink the allocated memory
(5 answers)
Can I assume that calling realloc with a smaller size will free the remainder? [duplicate]
(5 answers)
what will realloc do to the old pointer [duplicate]
(6 answers)
Closed 2 years ago.
I have a few questions about understanding
realloc behavior.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *str;
/* Initial memory allocation */
str = malloc(5 * sizeof(int));
*str = 1;
*(str + 1) = 2;
*(str + 2) = 3;
*(str + 3) = 4;
*(str + 4) = 5;
/* Reallocating memory */
int i, j;
for (i = 5; i > 0; i--) {
str = realloc(str, i * sizeof(int));
for (j = 0; j < i; j++) {
printf("%d", *(str + j));
}
printf("\n");
}
free(str);
return(0);
}
In this code example, can I be sure that a smaller realloc will drop the highest number?
Is the realloc is only freeing the last memory and keeping the same address in str? Or may the address change even though it's getting smaller and for sure have space in the current place?
Yes. If you have a memory block p of size N and you do realloc(p, M), then (assuming realloc succeeds), the result will contain the first min(N, M) bytes from p.
The address can change, even if the new size is smaller than the old one. realloc simply makes no guarantees about this case (it can even fail).

Allocate and initialize matrix using sizeof

Is it possible to allocate dynamically and initialize (and free) a matrix (or others multidimensional arrays) using sizeof operator instead of indexes and "standard" pointer arithmetic?
I've tried this:
#include <stdio.h>
#include <stdlib.h>
#define ROWS 3
#define COLUMNS 4
int main(void)
{
int i, j;
char **v;
if((v = malloc(ROWS*sizeof(char*)))==NULL)
return -1;
for(i=0; i<ROWS; i++)
{
if((*(v + i * sizeof(char*)) = malloc(COLUMNS * sizeof(char)))==NULL)
return -2;
}
for(i=0; i<ROWS; i++)
{
for(j=0; j<COLUMNS; j++)
{
*(*(v + i * sizeof(char*)) + j * sizeof(char)) = 'a' + i * COLUMNS + j;
printf("%c",*(*(v + i * sizeof(char*)) + j * sizeof(char)));
}
}
for(i=0; i<ROWS; i++)
{
free(*(v + i * COLUMNS * sizeof(char)));
}
free(v);
return 0;
}
but it generates a core dump (SIGSEGV at line 24 (v[1][0])). I believe the problem is in the allocation (maybe for the allocation v[1], v[2]... v[ROWS] malloc goes to write on the memory first allocated). Precisely, what is the problem?
Thanks.
It's because *(v + i * sizeof(char *)) is equivalent to v[i * sizeof(char *)] or *((unsigned char *) v + i * sizeof(char *) * sizeof(char *).
In pointer arithmetic, the increment is performed in units of the pointee type, in this case char *.
If you want to compute the offset yourself just cast the pointer to unsigned char * but that,
Is absolutely redundant, except in some situations where you don't want the pointer to have a definite type and it's void *, in that case casting to unsigned char * and incrementing the exact number of bytes is OK.
There is no good reason for that to be a requirement, you don't use the sizeof operator because it's a requirement but instead because you need to.
It's error prone and you can easily cause Undefined Behavior as it happens with your code, which has something even more disturbing
*(*(v + i * sizeof(char*)) + j * sizeof(char))
In detail,
There is no way that sizeof(char) will be different than 1, it's like multiplying by sin2(x) + cos2(x), it makes absolutely no sense.
You are incrementing the pointer way beyond the allocated space, becauseof the first point again.

C Matrix redimensioning leading to segfault

I've got a array of strings (char**) and I need to do some redimensioning on it when it has reached its capacity. So, in this function I create a new array, allocate a size two time bigger than before, and for each string in the old array I allocate space for the new array and copy the content. Code is as follows:
void matrix_double (char ***arrayptr, int *size) {
char **array = *arrayptr, **newarr;
int i, wordsize;
newarr = malloc (*size * 2);
for (i = 0; i < *size; i++) {
wordsize = strlen (array[i]);
newarr[i] = malloc (wordsize + 1);
strcpy (newarr[i], array[i]);
free (array[i]);
}
*size *= 2;
free (array);
*arrayptr = newarr;
}
However, I'm getting a lot of segfaults when allocating space for the new strings in the 7th line. According to Valgrind, those malloc commands are allocating space from within the space allocated for the array, which is small - I'm using arrays of 10 or 20 strings at most - and so it overflows to other allocated areas, causing segfaults. If I bump the array memory allocation up (such as malloc (*size * 200) everything runs smoothly.
Any ideas on what's happening? Haven't seen this behavior anywhere else.
malloc argument is size in bytes. So you should call it like
malloc(sizeof(char *) * (*size) * 2);
By calling
malloc(*size * 2);
you are allocating 2*size bytes of memory which is not enough for size of pointers.

Resources