Greetings all,
Is there any issue in the following logic for allocating 2D array:
unsigned char **
Malloc2D_uchr(int ht, int wt, unsigned char initv)
{
int h, w;
unsigned char **x;
x = (unsigned char **) malloc(sizeof(void *) * ht);
DEBUG_PRINT_MEMLOC_EXIT(x,"malloc failed (%s,%i)\n",sizeof(void *)*ht);
x[0] = (unsigned char *) malloc(sizeof(unsigned char) * ht * wt);
DEBUG_PRINT_MEMLOC_EXIT(x[0],"malloc failed (%s,%i)\n",sizeof(unsigned char)*ht*wt);
for (h = 1; h < ht; h++)
{
x[h] = x[h - 1] + wt; /* + is a pointer summation */
}
for (h = 0; h < ht; h++)
{
for (w = 0; w < wt; w++)
{
x[h][w] = initv;
}
}
return x;
}
The macro expansion is :
#define DEBUG_PRINT_MEMLOC_EXIT(t,s,z); if(t == NULL){\
printf(s,__FILE__,__LINE__,z);\
printf("Malloc size = %d\n",z);\
exit(-1);\
}
Sometimes the code crash during malloc().
thanks in advance.
There's nothing fundamentally wrong - that approach is perfectly cromulent. However, you should check that the multiplications don't overflow, and your malloc() lines can be written in a cleaner way:
if ((ht > SIZE_MAX / sizeof x[0]) || (wt > (SIZE_MAX / sizeof x[0][0]) / ht))
/* error, too large */
x = malloc(sizeof x[0] * ht);
x[0] = malloc(sizeof x[0][0] * ht * wt);
I'm surprised it doesn't crash all the time. You don't return anything.
Related
I've done this code to read an array, it works properly in the small tests (3x3), however i need it to read a 15x15 one. After 150 scans it has stopped working, returned 3221225477 and closed.
What is happening? How to fix it?
int ** ler(){
FILE *a;
a = fopen("matriz.txt", "r");
int **N;
int b, c, d;
N = malloc(15 * sizeof(int));
for (b = 0; b < 15; b++){
N[b] = malloc(15 * sizeof(int));
}
for (b = 0; b < 15; b++){
for (c = 0; c < 15; c++){
fscanf(a, "%i", &d);
N[b][c] = d;
}
}
return N;
}
At least this problem:
Wrong size allocation
int **N; // vvvvvvvvvvv This is the size of an int
//N = malloc(15 * sizeof(int));
N = malloc(15 * sizeof *N);
// ^^^^^^^^^ The size of a pointer is needed here
With OP's code, when the size of an int < size of an int *, the allocation is undersized.
Avoid that mistake and code with *N rather than attempting to match the type.
// Nice idiom
ptr = malloc(sizeof *ptr * n);
// ^^^^^^^^^^^ The right size regardless of what `ptr` pointers to.
Call fclose(a) when done reading.
I came across this question while looking for an effective way to allocate large multi-dimensional arrays contiguously in memory. The accepted answer suggests that for a 3D array of size sz[0] x sz[1] x sz[2] one should use this method, which is currently melting my feeble brain:
int (*a)[sz[1]][sz[2]] = calloc(sz[0], sizeof(*a));
...
free(a)
the left hand of that statement looks like a 2D array of int * allocated on the stack. The right side is a single (?!) call to calloc() that allocates int * on the heap. Since sizeof(*a)==sizeof(int *) (right?) this looks like too few allocations to make any sense, since it appears to allocate sz[0]x int * bytes, and yet it works to index over the full intended size of the array.
Can someone please help me understand how exactly this definition works to produce the intended result? Is the C compiler repeating the call to calloc for every entry in the table defined on the left? And if so, how does a single call to free() suffice to get rid of it? Does the resulting array reside entirely on the heap, or is it mixing a reference table on the stack that points to memory allocated on the heap?
Here is some code with a similar principle that maybe is easier to understand at first:
typedef int THING[5][6]; // THING means a contiguous array of 5x6 ints
THING arr[4]; // arr is a contiguous array of 4 THINGs
THING *first = &arr[0]; // The expression *first would yield the first thing.
Hopefully you recognize the last two lines here as being common syntax for non-dynamic allocation of any array, and referring to the array's first element. That works just the same whether or not THING is itself an array.
Now, &arr[0] points to a memory location that is the start of a contiguous block of ints of size 4x5x6. if you use dynamic allocation to make that block it looks like:
THING *first = malloc( sizeof(int[4][5][6]) );
If we expand out the typedef in this last line it looks like:
int (*first)[5][6] = malloc( sizeof(int[4][5][6]) );
The code in your question is the same as this last line , except that:
it uses variables instead of hardcoded integers (which is allowed since C99).
it uses calloc instead of malloc.
it uses a more robust syntax for calculating the size to allocate, see here for explanation.
To not rely on VLAs, but still use one continuous region of memory you could use this approach:
int *** int_array_3d_allocate(size_t x, size_t y, size_t z)
{
int *** result;
size_t n = x;
size_t s = n * sizeof *result; /* x vector of pointer to int** */
n *= y;
s += n * sizeof **result; /* x*y vectors of pointer to int* */
n *= z;
s += n * sizeof ***result; /* x*y*z int */
/* allocate it */
result = malloc(s);
if (result)
{
/* make the int** vector point to the int* vectors: */
for (size_t i = 0; i < x; ++i)
{
result[i] = (int**) ((char*) result) +
(x * sizeof *result +
i * y * sizeof **result);
}
/* make the int* vectors point to the int vectors: */
for (size_t i = 0; i < x*y; ++i)
{
((int**) ((char*) result + x * sizeof *result))[i] = (int*) ((char*) result) +
(x * sizeof *result + x*y * sizeof **result
+ i * sizeof ***result);
}
}
return result;
}
Version of the above code taking care of correct alignment of the int* and the int** blocks:
#include <stdalign.h>
int *** int_array_3d_allocate(size_t x, size_t y, size_t z)
{
int *** result;
size_t n = x;
size_t s = n * sizeof *result; /* x vector of pointer to int** */
size_t y_off = s % alignof **result
?alignof **result - s % alignof **result :0;
n *= y;
s += n * sizeof **result; /* x*y vectors of pointer to int* */
size_t z_off = s % alignof ***result
?alignof ***result - s % alignof ***result :0;
n *= z;
s += n * sizeof ***result; /* x*y*z int */
/* allocate it */
result = malloc(s);
if (result)
{
/* make the int** vector point to the int* vectors: */
for (size_t i = 0; i < x; ++i)
{
result[i] = (int**) ((char*) result) + y_off +
(x * sizeof *result +
i * y * sizeof **result);
}
/* make the int* vectors point to the int vectors: */
for (size_t i = 0; i < x*y; ++i)
{
((int**) ((char*) result + x * sizeof *result + y_off))[i] = (int*) ((char*) result) + y_off +
(x * sizeof *result + x*y * sizeof **result + z_off +
+ i * sizeof ***result);
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int *** int_array_3d_allocate(size_t x, size_t y, size_t z);
int main(void)
{
const size_t x = 2;
const size_t y = 3;
const size_t z = 5;
int *** int_array_3d = int_array_3d_allocate(x, y, z);
if (!int_array_3d)
{
perror("int_array_3d_allocate() failed");
}
else
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
for (size_t k = 0; k < z; ++k)
{
int_array_3d[i][j][k] = (int)(i*j*k);
}
}
}
/* do stuff with the continuous array of ints.
Just be aware that the 1st int only is located at address:
(char* int_array_3d) +
(x * sizeof *int_array_3d + x*y * sizeof **int_array_3d)
*/
free(int_array_3d);
}
}
If the array is handed off to functions, it decays into a pointer-to-pointer-to-pointer-to-int, making it unwieldy; one has to pass all the extra size information, too, or pass a pointer to a fixed size; see What is array decaying? A different way of handling arrays with multiple dimensions is an object which has the dimensions encoded within the object. This will compile in C90,
#include <stdlib.h> /* mallc, free, EXIT_ */
#include <errno.h> /* errno */
#include <stdio.h> /* perror, printf, fput[c|s] */
struct IntCube { size_t x, y, z; /* C99 supports FAM; would be useful. */ };
/** Returns a `struct IntCube` with `x`, `y`, `z` dimensions or null and
`errno` may be set. The caller is responsible for calling `free`. */
static struct IntCube *IntCube(const size_t x, const size_t y, const size_t z) {
struct IntCube *cube;
size_t xy_size, xyz_size, data_size, cube_size;
if(!x || !y || !z) return 0;
/* Check for overflow; <https://stackoverflow.com/q/1815367/2472827>. */
xy_size = x * y;
xyz_size = xy_size * z;
data_size = xyz_size * sizeof(int);
cube_size = sizeof cube + data_size;
if(xy_size / x != y
|| xyz_size / xy_size != z
|| data_size / xyz_size != sizeof(int)
|| cube_size < data_size) { errno = ERANGE; return 0; }
/* Allocate memory. */
if(!(cube = malloc(cube_size))) return 0; /* POSIX has defined errors. */
cube->x = x;
cube->y = y;
cube->z = z;
return cube;
}
static int *int_cube_get(const struct IntCube *cube,
const size_t x, const size_t y, const size_t z) {
return (int *)(cube + 1) + z * cube->y * cube->x + y * cube->x + x;
}
typedef void (*IntCubeAction)(const size_t x, const size_t y, const size_t z,
int *pnumber);
typedef void (*BinaryAction)(int bin);
/** Goes through `cube` and performs `action` on each number. It will call
optional binary action `bin` each time there is an
start(false)/end(true)-of-x/y. */
static void IntCubeForEach(struct IntCube *const cube,
const IntCubeAction action, const BinaryAction bin) {
size_t x, y, z;
if(!cube || !action) return;
for(z = 0; z < cube->z; z++) {
if(bin) bin(0);
for(y = 0; y < cube->y; y++) {
if(bin) bin(0);
for(x = 0; x < cube->x; x++) {
action(x, y, z, int_cube_get(cube, x, y, z));
}
if(bin) bin(1);
}
if(bin) bin(1);
}
}
/** #implements IntCubeAction */
static void fill_with_xyz(const size_t x, const size_t y, const size_t z,
int *pnumber) {
*pnumber = (x + 1) * (y + 1) * (z + 1);
}
/** #implements IntCubeAction */
static void print_cube(const size_t x, const size_t y, const size_t z,
int *pnumber) {
(void)y, (void)z;
printf("%s%d", x ? ", " : "", *pnumber);
}
/** #implements BinaryAction */
static void print_cube_corners(int bin) {
printf("%s", bin ? " }" : "{ ");
}
int main(void) {
struct IntCube *cube = 0;
int status = EXIT_FAILURE;
if(!(cube = IntCube(4, 3, 3))) goto catch;
IntCubeForEach(cube, &fill_with_xyz, 0);
IntCubeForEach(cube, &print_cube, &print_cube_corners);
fputc('\n', stdout);
status = EXIT_SUCCESS;
goto finally;
catch:
perror("Cube");
finally:
free(cube);
return status;
}
{ { 1, 2, 3, 4 }{ 2, 4, 6, 8 }{ 3, 6, 9, 12 } }{ { 2, 4, 6, 8 }{ 4, 8, 12, 16 }{ 6, 12, 18, 24 } }{ { 3, 6, 9, 12 }{ 6, 12, 18, 24 }{ 9, 18, 27, 36 } }
This creates a dependence on struct IntCube, but with the dependence, one can calculate the size at runtime.
I'm using an example from https://phoxis.org/2012/07/12/get-sorted-index-orderting-of-an-array/ where he returns the sort indices from a sort of an array, i.e.
3,4,2,6,8 returns 4,3,1,0,2 (+1 for each index in R). This is the equivalent of R's order function
I've translated his/her code to work as a function returning an array of sorted indices. The code gives the correct answer.
keeping track of the original indices of an array after sorting in C has a similar response, but as #BLUEPIXY warns, his solution doesn't work in all circumstances. I need something that will work in all circumstances, including ties.
however, the original author uses a global pointer, which causes a memory leak, and free() doesn't fix it. which I don't know how to do this without the global pointer.
How can I fix this memory leak, or at least return sorted indices in C that will always work?
#include <stdio.h>
#include <stdlib.h>
/* holds the address of the array of which the sorted index
* order needs to be found
*/
int * base_arr = NULL;
/* Note how the compare function compares the values of the
* array to be sorted. The passed value to this function
* by `qsort' are actually the `idx' array elements.
*/
static int compar_increase (const void * a, const void * b) {
int aa = *((int * ) a), bb = *((int *) b);
if (base_arr[aa] < base_arr[bb]) {
return 1;
} else if (base_arr[aa] == base_arr[bb]) {
return 0;
} else {
// if (base_arr[aa] > base_arr[bb])
return -1;
}
}
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
int main () {
const int a[] = {3,4,2,6,8};
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
for (size_t i = 0; i < sizeof(a)/sizeof(*a); i++) {
printf("b[%lu] = %d\n", i, b[i]+1);
}
free(b); b = NULL;
return 0;
}
A straightforward approach without using a global variable can look the following way
#include <stdio.h>
#include <stdlib.h>
int cmp_ptr(const void *a, const void *b)
{
const int **left = (const int **)a;
const int **right = (const int **)b;
return (**left < **right) - (**right < **left);
}
size_t * order_int(const int *a, size_t n)
{
const int **pointers = malloc(n * sizeof(const int *));
for (size_t i = 0; i < n; i++) pointers[i] = a + i;
qsort(pointers, n, sizeof(const int *), cmp_ptr);
size_t *indices = malloc(n * sizeof(size_t));
for (size_t i = 0; i < n; i++) indices[i] = pointers[i] - a;
free(pointers);
return indices;
}
int main( void )
{
const int a[] = { 3,4,2,6,8 };
const size_t N = sizeof(a) / sizeof(*a);
size_t *indices = order_int(a, N);
for (size_t i = 0; i < N; i++) printf("%d ", a[indices[i]]);
putchar('\n');
free(indices);
return 0;
}
The program output is
8 6 4 3 2
As for the memory leak then it is due to overwriting the value of the pointer to redundantly allocated memory.
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
The memory allocation does not make sense.
The problem I see is that within main function - you are allocating pointer b some memory -
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
The next line calls order_int(...) that returns a pointer to already allocated memory -
b = order_int(a, sizeof(a) / sizeof(*a));
Looking at the order_int function -
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
.. you see that idx has been already been allocated the correct memory.
I would suggest removing the malloc from b - see below.
int * b = NULL;
Suppose we have this code:
int *h;
for(int i=0;i<5;i++){
h = malloc(sizeof(int));
h[i] = i;
}
The issue I have here is that I want to start with an empty array, i.e. just declaringint *h, and then *h will grow at the runtime using realloc. I tried using this example but it does not allocate a sequential memory places and also does not work. I understand that realloc works after allocating by malloc so is there any workaround of that?
To accommodate exactly what you are trying to do, realloc(NULL, size) does the same thing as malloc(size). You can write your loop like this:
int *h = 0;
size_t avail = 0;
for (size_t i = 0; more_data_available(); i++) {
if ((i+1) * sizeof(int) > avail) {
avail = avail == 0 ? 8*sizeof(int) : avail*2;
int *nh = realloc(h, avail);
if (!nh) abort();
h = nh;
}
h[i] = next_data_item();
}
But note the convoluted ?: expression I had to use to enlarge avail. That would be cleaner if I start the loop with some space already allocated; and then I can just use malloc normally:
size_t avail = 8 * sizeof(int);
int *h = malloc(avail);
if (!h) abort();
for (size_t i = 0; more_data_available(); i++) {
if ((i+1) * sizeof(int) > avail) {
avail *= 2;
int *nh = realloc(h, avail);
if (!nh) abort();
h = nh;
}
h[i] = next_data_item();
}
I am working on a custom malloc and free implementation in C. My code works fine, but not perfectly. In my file that tests my_malloc and my_free, I call my_malloc 3 times. It works for the first 2 calls, but doesn't for the 3rd call. Everything is exactly the same, so I really have no idea why it wouldn't work again. I know there's enough memory in the heap, so it's not that. It even works to the point of returning an address for the pointer variable, but the test file won't write to it.
Here's the bit of code to test my_malloc and my_free, it breaks with c:
static int *base;
static int *heap_end;
int total_mem_used = 0;
int first_call = 1;
int i;
int *a, *b, *c;
if ((a=(int *)my_malloc(10))==NULL)
return MALLOC_FAIL;
for (i=0;i<10;i++)
a[i] = i;
for (i=0;i<10;i++)
printf("%d\n", a[i]);
if ((b=(int *)my_malloc(18))==NULL)
return MALLOC_FAIL;
for (i=0;i<18;i++)
b[i] = i*i;
for (i = 0; i < 18; i++)
printf("%d ", b[i]);
printf("\n");
if ((c=(int *)my_malloc(5))==NULL)
return MALLOC_FAIL;
for (i=0;i<5;i++)
c[i] = i*7;
Here's my_malloc too, if it helps:
void *p;
int *t;
int data_size, block;
if (size==0)
return NULL;
if (first_call) {
if ((base=(int *)malloc(HEAP_SIZE))==NULL)
return NULL;
init_heap(norm_size(size)+8);
heap_end = &base[HEAP_SIZE];
first_call = 0;
total_mem_used += (norm_size(size)+2);
t = base;
return (void *) (t+2);
}
data_size = norm_size(size);
block = data_size + 2;
p = find_first_free(block);
if (p==0) {
errno = ENOMEM;
return NULL;
}
total_mem_used += block;
fill_header((int *) p, block);
t = (int *) p + 2;
return (void *) t;
void my_free(void *p) {
int *t;
t = (int *) p - 2;
*t = *t & -2;
coalesce(t);
}
void *find_first_free(int n) {
int *p;
p = base;
while (p<heap_end && ((*p & 1) || (*p <= n)))
p = p + (*p & -2);
return (void *)p;
}
int norm_size(int w) {
if (w % 8 == 0)
return w;
else
return w + (8 - w % 8);
}
void init_heap(int n) {
base[0] = n+1; // n+1 since we're allocating it
base[1] = (int) &base[n];
base[n-1] = n+1;
base[n] = HEAP_SIZE - n;
base[HEAP_SIZE-1] = HEAP_SIZE - n;
}
void fill_header(int *p, int w) {
p[0] = w+1;
p[1] = (int) &p[w];
p[w-1] = w+1;
p[w] = HEAP_SIZE - total_mem_used;
p[w+HEAP_SIZE-total_mem_used-1] = HEAP_SIZE - total_mem_used;
}
Any idea what exactly is wrong with the program? Thanks for any help.
Avoid magic numbers
block = data_size + 2;
Why 2? why not 16 or 256? Certainly the addition is done to provide for saving the size. In that case, add the size of the int.
block = data_size + sizeof(int);
t = (int *) p + 2;
Why 2 versus any other number? Again, this is done to account for the size begin saved at p. But this is not integer addition like before. This is "pointer addition". With + 2, p is increased by the 2 * sizeof(int). Likely code should be
t = p + 1;
This is an exception to the "no magic numbers" rule: -1,0,+1 are OK
To answer more, post complete functions.
Minor: cast not needed
// if ((base=(int *)malloc(HEAP_SIZE))==NULL)
if ((base = malloc(HEAP_SIZE)) == NULL)
Minor: Consider the unsigned type size_t. That is the type returned by functions/operators like strlen(), sizeof()
// int data_size
size_t data_size
// if ((a=(int *)my_malloc(10))==NULL)
a = my_malloc(10);
if (a == NULL)
Why 8 in init_heap(norm_size(size)+8);? Use a constant/define
#define MY_MALLOC_GUARD (8)
init_heap(norm_size(size) + MY_MALLOC_GUARD);