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.
Related
I have code like this:
#include <stdio.h>
#include <stdlib.h>
int main() {
int x=10;
int y=10;
int **data = (int**) malloc(x * sizeof(int));
if(!**data){
printf("Error");
return 1;
}
for(int i=0;i<x;i++){
*(data+i) = (int*) malloc(y * sizeof(int));
if(!*(data+i)){
printf("Error");
return 1;
}
}
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
data[i][j]=(i+1)*(j+1);
}
}
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
printf("%3i ",data[i][j]);
}
printf("\n");
}
return 0;
}
How can i access points of that array using pointers instead of data[i][j]?
I tried searching for answer but in every example I see people use data[x][y] option, i have to use pointers for accessing each element.
Also is error handling correct in that code?
if(!**data){
printf("Error");
return 1;
}
Here's a major problem, especially on 64-bit systems where sizeof(int) != sizeof(int *):
int **data = (int**) malloc(x * sizeof(int));
You allocate x times the size of int, not the size of pointer to int.
There is a good "trick" to always get the correct size, use sizeof *variable_youre_allocating_for. In your case it would be
int **data = malloc(x * sizeof *data);
This works because sizeof *data is done at compile-time, and the compiler knows that *data is of type int * and will use the correct size.
Also notice that I removed the cast, it's not needed in C.
Besides that, your use of the data is correct. Using data[i][j] is perfectly fine, if i and j are valid indexes, and data and data[i] have been properly initialized.
The important part is to remember that for any pointer or array a and index i, the expression a[i] is exactly equal to *(a + i). In fact, the compiler will translate a[i] to *(a + i). So for your pointer data, the expression *(data + i) is exactly equal to data[i]. And the latter is usually easier to read and understand, as well as less to write.
Often malloc is used to allocate memory for n elements of some primitive datatype (int, float, char). This could look like this:
#define N 10
double *mem = malloc(N * sizeof(double));
for (int i = 0; i < N; ++i) {
mem[i] = 10.0; // Write
double d = mem[i]; // Read
}
This would even work if I declared mem as char * and used a cast later on:
char *mem = malloc(N * sizeof(double));
for (int i = 0; i < N; ++i) {
*(double*)(mem + i * sizeof(double)) = 10.0;
double d = *(double *)(mem + i * sizeof(double));
}
Currently I'm wondering if this is well defined and working for every datatype (even any complex type like struct). Lets assume struct a could be anything. Is the following well defined?
char *mem = malloc(N * sizeof(struct a));
for (int i = 0; i < 10; ++i)) {
*(struct a *)(mem + i * sizeof(struct a)) = /* something valid */;
struct a x = *(struct a *)(mem + i * sizeof(struct a));
}
Since the return value of malloc is suitably aligned for any kind of variable the case i = 0 is definitely well defined and working, but how about I = 1, 2, ...? Will alignment screw this up? Like in this example:
char char_arr[4] = /* some value */;
int *d = &char_arr[0];
The second line is not guaranteed to work, since char_arr may not be aligned on a 4-byte boundary (required for int).
Is the following well defined?
char *mem = malloc(N * sizeof(struct a));
for (int i = 0; i < N /* 10 */; ++i)) {
*(struct a *)(mem + i * sizeof(struct a)) = /* something valid */;
// struct a = *(struct a *)(mem + i * sizeof(struct a));
struct a x = *(struct a *)(mem + i * sizeof(struct a));
}
Almost always.
In terms of alignment, *alloc() returns a pointer to memory that is valid for all fundamental alignments as OP noted. (struct a *)(mem + i * sizeof(struct a)) will also provide a well aligned pointer for all 0 <= i <= N.
Not a likely concern for OP, yet on rare machines i * sizeof(struct a) will overflow size_t math (with a large enough i and sizeof(struct a), whereas mem[i] will not. This is not seen on common implementations that use a flat memory address.
Also robust code checks for memory allocation failures.
Candidate simplified code. Notice the type ptr points to is not relevant, assuming it is not defined void *ptr. #usr.
ptr = malloc(sizeof *ptr * N);
if (ptr == NULL) Handle_OOM();
for (size_t i = 0; i < N; ++i)) {
ptr[i] = /* something valid */;
}
`
Yes, you can use malloc to allocate array of structures.
7.22.3 Memory management functions
The order and contiguity of storage allocated by successive calls to the
aligned_alloc, calloc, malloc, and realloc functions is unspecified. The
pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to
a pointer to any type of object with a fundamental alignment requirement and then used
to access such an object or an array of such objects in the space allocated (until the space
is explicitly deallocated). ...
But you don't need to do all that ugly casting:
struct a *mem = malloc(N * sizeof(struct a));
for (int i = 0; i < 10; ++i)) {
mem[i] = /* something valid */;
struct a var = mem[i];
}
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.
I want to create a bidimensional array like so:
void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * 4);
if(m==NULL)
return NULL;
for(i=0; i<nrLini; i++)
{
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
if(*(m + (i*4)) == NULL)
return NULL;
}
return m;
}
I whant to use it like this:
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
but it doesn't work. What do I do wrong?
You should use m[i] instead of *(m+i*4) and let the compiler do the arithmetic.
In addition, you should deallocate the already-allocated memory in case of a failure.
Try this instead:
void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * sizeof(void*));
if (m == NULL)
return NULL;
for (i=0; i<nrLini; i++)
{
m[i] = malloc(nrColoane * sizeOfElement);
if (m[i] == NULL)
{
while (i-- > 0)
free(m[i]);
free(m);
return NULL;
}
}
return m;
}
[not an answer to the question, but to the indented usage of the proper answer as given by others]
To access the void pointer array as an array of int, doing this
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
is not correct, as per the C-Standard only void* converts to any other pointer properly, void** doesn't necessarily. So it shall correctly be
void ** ppv = mdeclaraMatrice(n,m,sizeof(int));
int * pi = *ppv; /* Please note, there is NO casting necessary here! */
Then access the members like so:
pi[0] = 42
pi[1] = 43;
...
Which essently is the same as doing
*((int *) (pi + 0)) = 42;
*((int *) (pi + 1)) = 43;
which indeed does not make sense really as pi already is int*, so the fully correct approach (also taking into account the 2nd dimension) would be:
((int *)(ppv[0]))[0] = 42;
((int *)(ppv[0]))[1] = 43;
Which could be made usable by definging a macro:
#define GENERIC_ARRAY_ELEMENT(type, address, r, c) \
((type *)(address[r]))[c]
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42;
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43;
I will address the problem of allocation an array of void pointers and then interpreting them as an array of int pointers.
int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int));
Even assuming the allocation was completely correct the assignment and later usage of nope is undefined behavior. void** and int** have incompatible types.
What you can do is the following. Assign the void pointers one by one to an array of int pointers.
void** arrp = mdeclaraMatrice(n,m,sizeof(int));
int* arr[n] ;
for( size_t i = 0 , i < n ; i++ )
arr[i] = arrp[i] ;
And then use the arr array, When you want to free the memory you free the original pointer:
free( arrp ) ;
The problem occurs in this line:
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
You have to know that when adding a number to an address, the address will be incremented by the number times the size of the object the address points to. So if your pointer points to an object that is of size 4 bytes, and you add 1 to it, then the address will automatically be incremented by 4, not by 1. So you should abandon *4.
Also, use the sizeof operator when allocating space, because addresses (and thus pointers) can have different sizes on different processor architectures.
Actually, you don't even need your generic 2D array function if you know the powerfull VLA features of C99. To allocate a true 2D array (no index array required), you just do this:
int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray));
That's it. Accesses are just as simple:
twoDIntArray[line][column] = 42;
In this code, twoDIntArray is a pointer to an array of width integers. The malloc() call simply allocates enough space for height such line arrays. When you do the pointer arithmetic twoDIntArray[line], you add the size of line line arrays to the pointer, which produces the address of the corresponding line array. This line array is then indexed by the second array subscript [column].
Needless to say that freeing such an array is just as trivial:
free(twoDIntArray);
I want to declare the correct pointer and allocate memory for a two-dimensional array, and correctly pass to a function. I am having trouble getting this to work properly and need help.
Here is my code:
double **podrucje;
podrucje=(double **) malloc (sizeof (double *) *123);
for (i=0;i<(123);i++)
{
podrucje[i]=(double *) malloc (sizeof (double) * 11);
}
for (i=0;i<(123);i++)
{
memset (podrucje[i], 0, 10);
}
But this code doesnt work, it messes up whole my program. So i decided to give up on dynamic allocation and use this:
double podrucje[123][11]={0};
But i dont know how to send it and use it in function...
memset works on per byte basis.
double **podrucje = (double **) malloc (sizeof (double *) * 123);
for (i = 0; i < 123; i++)
{
podrucje[i] = (double *) malloc (sizeof (double) * 11);
memset(podrucje[i], 0, sizeof(double) * 11);
}
if you want to pass it just declare it as such
void function(double podrucje[123][11]) {
...
}
You're best off to use malloc, but allocate the whole array on your second line, so it all gets allocated in contiguous memory. So
podrucje = (double*) malloc (sizeof (double) * 123 * 11);
Then the first loop can go away too. And it looks like you're initializing the array to 0 -- in that case, use calloc instead of malloc, eliminating the second loop.
To index into the array, use things like
double myitem = podrucje [11 * row + col];
You should of course use a define or similar to keep the use of 11 consistent, but that's not the point of this answer.
Write the function argument the same way you wrote the variable definition:
void myfunc(double podrucje[123][11])
{
...
}
double podrucje[123][11];
myfunc(podrucje);
Note that the array is passed "by reference" rather than being copied.
In the following code snippet,
podrucje[i]=(double *) malloc (sizeof (double) * 11);
for (i=0;i<(123);i++)
{
memset (podrucje[i], 0, 10);
}
1) You dont need the extra parenthesis against the numbers 123 and 11
The for loop can be as follows,
for (i = 0; i < 123; i++)
2) Instead of using 123 and 11. Try to define a MACRO and use that instead.
Advantage: The code becomes independent of special numbers and is easily maintainable. Especially in the cases of larger code base.
3) If you read the code, podrucje[i] is allocated a memory of 11 doubles But when you memset you are setting it for only 10 doubles while the last one may or may not consist of garbage. Use calloc here, It not only allocated memory but also initializes the same.
podrucje[i]=(double *) calloc(11,sizeof(double));
Also It could be more helpful if you could tell How exactly is it screwing up your code ?
Example, Code Snippet could help more than just stating its screwing up.
It helps others to investigate and solve the issue.
If you have a modern C compiler (C99 would do) you can even declare real 2D matrices with variable sizes. You don't need to fall back to this awful emulation with pointers.
void myfunc(size_t n, size_t m, double podrucje[n][m])
{
...
}
double (*podrucje)[n] = malloc(sizeof(double[n][m]));
myfunc(n, m, podrucje);
For the function you just have to ensure that the declarations of n and m come first, before the matrix.
There are several ways to dynamically allocate memory for an NxM array. Here are two:
You can declare a pointer to an M-element array, and then malloc N instances of it:
double (*podrucje)[11] = malloc(sizeof *podrucje * 123);
As of C89, you don't need to cast the result of malloc, and the practice is discouraged. Also, note that the operand to sizeof is the expression *podrucje; this gives me the same result as sizeof (double) * 11.
You would index this array as podrucje[i][j] like any other 2D array. podrucje[i] implicitly dereferences the pointer (remember that a[i] is equivalent to *(a + i)) so you don't have to do anything funky with it.
You would use it in a function as follows:
void init(double (*podrucje)[11], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < 11; j++)
podrucje[i][j] = 0.0;
}
which would be called as
init(podrucje, 123);
The drawback to this method is that the function can only operate on Nx11 arrays; if you're using a C99 compiler or a C2011 compiler that supports variable length arrays, you could specify the number of columns as a runtime variable:
void foo(void)
{
size_t rows = 123, cols = 11;
double (*podrucje)[cols] = malloc(sizeof *podrucje * rows);
if (podrucje)
init(cols, podrucje, rows);
...
}
// cols must be declared before it can be used
// in an array declarator
//
void init(size_t cols, double(*podrucje)[cols], size_t rows)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
When you're done with the array, deallocate it as follows:
free(podrucje);
The other approach is to allocate each row separately, as follows:
size_t rows = 123, cols = 11;
double **podrucje = malloc(sizeof *podrucje * rows);
if (!podrucje)
{
// malloc failed; handle allocation error here
}
else
{
size_t i;
for (i = 0; i < rows; i++)
{
podrucje[i] = malloc(sizeof *podrucje[i] * cols);
if (!podrucje[i])
{
// malloc failed; handle allocation error here
}
}
}
And you would use it in a function as follows:
void foo()
{
double **podrucje;
// allocate array as above
init(foo, rows, cols);
...
}
void init(double **podrucje, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
podrucje[i][j] = 0.0;
}
When you're finished with the array, deallocate it as follows:
for(i = 0; i < rows; i++)
free(podrucje[i]);
free(podrucje);
The first method allocates memory as a single, contiguous block; the second allocates it in a series of smaller, discontinuous chunks. If your array is especially big or your heap especially fragmented, the first method may fail where the second will succeed. If you're working with a compiler that doesn't support variable-length arrays, the first method is much less flexible, because the number of columns must be specified at compile time.
How could the same indexing method work for both forms?
In the first case, each podrucje[i] is an 11-element array of double; indexing it with j works like any other array. In the second case, each podrucje[i] is a pointer to double. Since a[i] is evaluated as *(a + i), array indexing works on pointer expressions just as well as array expressions.
int print_func(char((*p)[26])[10])
{
int i = 0;
for (i=0; i < 26 ; i++) {
fprintf(stderr, "%02d:%.*s\n", i, 10, p[0][i]);
}
return (0);
}
int main(void)
{
int nrow = 26;
int ncol = 10;
char((*p)[26])[10] = (char((*)[26])[10])(0);
char(*q)[10];
char c = 'a';
int i = 0;
p = (char((*)[26])[10])malloc(sizeof(char) * nrow * ncol);
if ((char((*)[26])[10])0 == p) {
return (-1);
}
for (i=0, q=p[0]; i < nrow ; i++) {
memset(q, c, sizeof(char) * ncol);
c++;
q++;
}
for (i=0,q=p[0] ; i < nrow ; i++) {
fprintf(stderr, "%.*s\n", 10, q);
q++;
}
p[0][8][0]='z';
getchar();
print_func(p);
return (0);
}