I am playing around with multidimensional array of unequal second dimension size.
Lets assume that I need the following data structure:
[&ptr0]->[0][1][2][3][4][5][6][7][8][9]
[&ptr1]->[0][1][2]
[&ptr2]->[0][1][2][3][4]
int main()
{
int *a[3];
int *b;
int i;
a[0] = (int *)malloc(10 * sizeof(int));
a[1] = (int *)malloc(2 * sizeof(int));
a[2] = (int *)malloc(4 * sizeof(int));
for(i=0; i<10; i++) a[0][i]=i;
for(i=0; i<2; i++) a[1][i]=i;
for(i=0; i<4; i++) a[2][i]=i;
}
I did some tests and it seems like I can store a value at a[1][3]. Does it mean that rows in my array are of equal size 10?
No, The address a[1][3] does not "officially exist". It is a memory which is not define in your program and accessing it result in a undefined behavior.
It can lead to the following error:
Segmentation fault (access a
restricted memory)
Used a memory already used by other variable (other allocation memory) (so possible overwrite)
It can be an uninitialized value (unsused memory address)
It is undefined behavior of your code. You are accessing something that you don't own. It may work, it may not, but it is always wrong.
No
There is lots of memory in your program used for I/O buffers, library data structures, the malloc system itself, command line arguments and environment, etc. (Some of those are on the stack.)
Yes, you can clobber things out of range.
Keep in mind that x[i] is the same thing as *(x + i). So, it's easy to calculate the address you referenced. It may overlay one of your data structures, it may overlay a part of your data structure that is a private field within malloc's mechanism, or it may overlay library data.
Related
So I am learning how to program in C, and am starting to learn about dynamic memory allocation. What I know is that not all the time will your program know how much memory it needs at run time.
I have this code:
#include <stdio.h>
int main() {
int r, c, i, j;
printf("Rows?\n");
scanf("%d", &r);
printf("Columns?\n");
scanf("%d", &c);
int array[r][c];
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
array[i][j] = rand() % 100 + 1;
return 0;
}
So if I wanted to create a 2D array, I can just declare one and put numbers in the brackets. But here in this code, I am asking the user how many rows and columns they would like, then declaring an array with those variables, I then filled up the rows and columns with random integers.
So my question is: Why don't I have to use something like malloc here? My code doesn't know how many rows and columns I am going to put in at run time, so why do I have access to that array with my current code?
So my question is: why don't I have to use something like malloc here?
My code doesn't know how many rows and columns I am going to put in at
run time, so why do I have access to that array with my current code?
You are using a C feature called "variable-length arrays". It was introduced in C99 as a mandatory feature, but support for it is optional in C11 and C18. This alternative to dynamic allocation carries several limitations with it, among them:
because the feature is optional, code that unconditionally relies on it is not portable to implementations that do not support the feature
implementations that support VLAs typically store local VLAs on the stack, which is prone to producing stack overflows if at runtime the array dimension is large. (Dynamically-allocated space is usually much less sensitive to such issues. Large, fixed-size automatic arrays can be an issue too, but the potential for trouble with these is obvious in the source code, and it is less likely to evade detection during testing.)
the program still needs to know the dimensions of your array before its declaration, and the dimensions at the point of the declaration are fixed for the lifetime of the array. Unlike dynamically-allocated space, VLAs cannot be resized.
there are contexts that accommodate ordinary, fixed length arrays, but not VLAs, such as file-scope variables.
Your array is allocated on the stack, so when the function (in your case, main()) exits the array vanishes into the air. Had you allocated it with malloc() the memory would be allocated on the heap, and would stay allocated forever (until you free() it). The size of the array IS known at run time (but not at compile time).
In your program, the array is allocated with automatic storage, aka on the stack, it will be released automatically when leaving the scope of definition, which is the body of the function main. This method, passing a variable expression as the size of an array in a definition, introduced in C99, is known as variable length array or VLA.
If the size is too large, or negative, the definition will have undefined behavior, for example causing a stack overflow.
To void such potential side effects, you could check the values of the dimensions and use malloc or calloc:
#include <stdio.h>
#include <stdlib.h>
int main() {
int r, c, i, j;
printf("Rows?\n");
if (scanf("%d", &r) != 1)
return 1;
printf("Columns?\n");
if (scanf("%d", &c) != 1)
return 1;
if (r <= 0 || c <= 0) {
printf("invalid matrix size: %dx%d\n", r, c);
return 1;
}
int (*array)[c] = calloc(r, sizeof(*array));
if (array == NULL) {
printf("cannot allocate memory for %dx%d matrix\n", r, c);
return 1;
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
array[i][j] = rand() % 100 + 1;
}
}
free(array);
return 0;
}
Note that int (*array)[c] = calloc(r, sizeof(*array)); is also a variable length array definition: array is a pointer to arrays of c ints. sizeof(*array) is sizeof(int[c]), which evaluates at run time to (sizeof(int) * c), so the space allocated for the matrix is sizeof(int) * c * r as expected.
The point of dynamic memory allocation (malloc()) is not that it allows for supplying the size at run time, even though that is also one of its important features. The point of dynamic memory allocation is, that it survives the function return.
In object oriented code, you might see functions like this:
Object* makeObject() {
Object* result = malloc(sizeof(*result));
result->someMember = ...;
return result;
}
This creator function allocates memory of a fixed size (sizeof is evaluated at compile time!), initializes it, and returns the allocation to its caller. The caller is free to store the returned pointer wherever it wants, and some time later, another function
void destroyObject(Object* object) {
... //some cleanup
free(object);
}
is called.
This is not possible with automatic allocations: If you did
Object* makeObject() {
Object result;
result->someMember = ...;
return &result; //Wrong! Don't do this!
}
the variable result ceases to exist when the function returns to its caller, and the returned pointer will be dangling. When the caller uses that pointer, your program exhibits undefined behavior, and pink elephants may appear.
Also note that space on the call stack is typically rather limited. You can ask malloc() for a gigabyte of memory, but if you try to allocate the same amount as an automatic array, your program will most likely segfault. That is the second reason d'etre for malloc(): To provide a means to allocate large memory objects.
The classic way of handling a 2D array in 'C' where the dimensions might change is to declare it as a sufficiently sized one dimensional array and then have a routine / macro / calculation that calculates the element number of that 1D array given the specified row, column, element size, and number of columns in that array.
So, let's say you want to calculate the address offset in a table for 'specifiedRow' and 'specifiedCol' and the array elements are of 'tableElemSize' size and the table has 'tableCols' columns. That offset could be calculated as such:
addrOffset = specifiedRow * tableCols * tableElemSize + (specifiedCol * tableElemSize);
You could then add this to the address of the start of the table to get a pointer to the element desired.
This is assuming that you have an array of bytes, not integers or some other structure. If something larger than a byte, then the 'tableElemSize' is not going to be needed. It depends upon how you want to lay it out in memory.
I do not think that the way that you are doing it is something that is going to be portable across a lot of compilers and would suggest against it. If you need a two dimensional array where the dimensions can be dynamically changed, you might want to consider something like the MATRIX 'object' that I posted in a previous thread.
How I can merge two 2D arrays according to row in c++
Another solution would be dynamically allocated array of dynamically allocated arrays. This takes up a bit more memory than a 2D array that is allocated at compile time and the elements in the array are not contiguous (which might matter for some endeavors), but it will still give you the 'x[i][j]' type of notation that you would normally get with a 2D array defined at compile time. For example, the following code creates a 2D array of integers (error checking left out to make it more readable):
int **x;
int i, j;
int count;
int rows, cols;
rows = /* read a value from user or file */
cols = /* read a value from user of file */
x = calloc(sizeof(int *), rows);
for (i = 0; i < rows; i++)
x[i] = calloc(sizeof(int), cols);
/* Initial the 2D array */
count = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
count++;
x[i][j] = count;
}
}
One thing that you need to remember here is that because we are using an array of arrays, we cannot always guarantee that each of the arrays is going to be in the next block of memory, especially if any garbage collection has been going on in the meantime (like might happen if your code was multithreaded). Even without that though, the memory is not going to be contiguous from one array to the next array (although the elements within each array will be). There is overhead associated with the memory allocation and that shows up if you look at the address of the 2D array and the 1D arrays that make up the rows. You can see this by printing out the address of the 2D array and each of the 1D arrays like this:
printf("Main Array: 0x%08X\n", x);
for (i = 0; i < rows; i++)
printf(" 0x08X [%04d], x[i], (int) x[i] - (int) x);
When I tested this with a 2D array with 4 columns, I found that each row took up 24 bytes even though it only needs 16 bytes for the 4 integers in the columns.
I want to create a variable length array for my code in the Visual Studio 2010 environment.
I had tried the code using the array of length x, as it is passing by the user. But I am facing the error as:
"error C2466:cannot allocate an array of constant size 0" ,"error C2133: 'v_X_array' : unknown size".
func1(int x)
{
int v_X_array[x];
int i;
for (i=0; i<x; i++)
{
v_X_array[i] = i;
}
}
I expect the answer as v_X_array[0] = 0, v_X_array[1] =1, v_X_array[2]=2 ... v_X_array[10]=10 ; for x = 10;
How can I do this?
Note: as calloc and malloc should not be used.
If you need your code to be portable, you cannot use that kind of array definition to handle memory areas.
Without going into specific implementations, you have two generic approaches that you can use:
Define an array big enough for the worst case. This is tightly dependent on the application, so you are on your own.
Define the "array" using dynamic allocation. With that, you can define memory areas of any arbitrary size.
If you choose option 2:
a. Do not forget to de-allocate the memory when you no longer need it.
b. To avoid frequent allocation and de-allocation, you may define the buffer once (perhaps bigger then necessary for the current call) and use it several times. You may and up with the same result as option 1 above - define a large array from the start.
Since you should not use dynamic allocation ("calloc and malloc should not be used"), then you are left with option 1.
I expect the ans as v_X_array[0] = 0, v_X_array[1] =1, v_X_array[2]=2 ... v_X_array[10]=10 ; for x = 10;
You expect to store 11 values in an array which can hold only 10?
You can't allocate an array of an unknown size.
So you need to allocate it dynamically "at run-time".
you can make this allocation using "new" in C++ or "malloc" in C.
For example:
In C++ if you want to allocate an array of an unknown size you should do the following:
int* v_X_array = new int[x];
int i;
for (i=0; i<x; i++)
{
v_X_array[i] = i;
}
The reason that we use integer pointer is that "new" returns the base address of the array "the address of the first element", so the only thing that can store addresses is pointers.
In C if you want to allocate an array of an unknown size you should do the following:
int* v_X_array = (int*) malloc(x*sizeof(int));
int i;
for(i=0; i<x; i++)
{
v_X_array[i] = i;
}
The malloc function takes a single argument which specifies the number of bytes to be allocated and returns a void pointer so the casting (int*) is required.
For more explanations, look at the next section:
If we need to allocate an array of 20 integers it could be as follow: "malloc(20*sizeof(int))" where 20 is the number of allocated elements and sizeof(int) is the size of the type you want to allocate. If successful it returns a pointer to memory allocated. If it fails, it returns a null pointer.
Enter image description here
I have this code segment:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int ** ar;
int i;
ar = malloc( 2 * sizeof(int*));
for(i=0; i<2; i++)
ar[i] = malloc ( 3 * sizeof(int) );
ar[0][0]=1;
ar[0][1]=2;
ar[0][2]=5;
ar[1][0]=3;
ar[1][1]=4;
ar[1][2]=6;
for(i=0; i<2; i++)
free(ar[i]);
free(ar);
printf("%d" , ar[1][2]);
return 0;
}
I went through some threads on this topic
(how to free c 2d array)
but they are quite old and no one is active.
I had the following queries with respect to the code:
Is this the correct way to free memory for a 2D array in C?
If this is the correct way then why am I still getting the corresponding array value when I try to print ? Does this mean that memory is not getting freed properly ?
What happens to the memory when it gets freed? Do all values which I have stored get erased or they just stay there in the memory which is waiting for reallocation?
Is this undefined behaviour expected?
Yes you have two levels or layers (so to speak) of memory to free.
The inner memory allocations (I like how you do those first)
The outer memory allocation for the topmost int** pointer.
Even after you freed the memory, nothing was done with it to overwrite it (So yes it's expected). Hence why you can still print them to the console. It's a good idea to always NULL your pointers after you are done with them. Kind of the polite thing to do. I've fixed many bugs and crashes in the past because the code did not null the pointers after freeing them.
In Microsofts Visual Studio, with the Debug C runtime, it can overwrite the newly free'd values with some garbage that will immediately raise an access violation if used, or dereferenced. That's useful for flushing out bugs.
It looks like you are new to C (Student?). Welcome and have a fun time.
It is more than one questions. I need to deal with an NxN matrix A of integers in C. How can I allocate the memory in the heap? Is this correct?
int **A=malloc(N*sizeof(int*));
for(int i=0;i<N;i++) *(A+i)= malloc(N*sizeof(int));
I am not absolutely sure if the second line of the above code should be there to initiate the memory.
Next, suppose I want to access the element A[i, j] where i and j are the row and column indices starting from zero. It it possible to do it via dereferencing the pointer **A somehow? For example, something like (A+ni+j)? I know I have some conceptual gap here and some help will be appreciated.
not absolutely sure if the second line of the above code should be there to initiate the memory.
It needs to be there, as it actually allocates the space for the N rows carrying the N ints each you needs.
The 1st allocation only allocates the row-indexing pointers.
to access the element A[i, j] where i and j are the row and column indices starting from zero. It it possible to do it via dereferencing the pointer **
Sure, just do
A[1][1]
to access the element the 2nd element of the 2nd row.
This is identical to
*(*(A + 1) + 1)
Unrelated to you question:
Although the code you show is correct, a more robust way to code this would be:
int ** A = malloc(N * sizeof *A);
for (size_t i = 0; i < N; i++)
{
A[i] = malloc(N * sizeof *A[i]);
}
size_t is the type of choice for indexing, as it guaranteed to be large enough to hold any index value possible for the system the code is compiled for.
Also you want to add error checking to the two calls of malloc(), as it might return NULL in case of failure to allocate the amount of memory requested.
The declaration is correct, but the matrix won't occupy continuous memory space. It is array of pointers, where each pointer can point to whatever location, that was returned by malloc. For that reason addressing like (A+ni+j) does not make sense.
Assuming that compiler has support for VLA (which became optional in C11), the idiomatic way to define continuous matrix would be:
int (*matrixA)[N] = malloc(N * sizeof *matrixA);
In general, the syntax of matrix with N rows and M columns is as follows:
int (*matrix)[M] = malloc(N * sizeof *matrixA);
Notice that both M and N does not have to be given as constant expressions (thanks to VLA pointers). That is, they can be ordinary (e.g. automatic) variables.
Then, to access elements, you can use ordinary indice syntax like:
matrixA[0][0] = 100;
Finally, to relase memory for such matrices use single free, e.g.:
free(matrixA);
free(matrix);
You need to understand that 2D and higher arrays do not work well in C 89. Beginner books usually introduce 2D arrays in a very early chapter, just after 1D arrays, which leads people to assume that the natural way to represent 2-dimensional data is via a 2D array. In fact they have many tricky characteristics and should be considered an advanced feature.
If you don't know array dimensions at compile time, or if the array is large, it's almost always easier to allocate a 1D array and access via the logic
array[y*width+x];
so in your case, just call
int *A;
A = malloc(N * N * sizeof(int))
A[3*N+2] = 123; // set element A[3][2] to 123, but you can't use this syntax
It's important to note that the suggestion to use a flat array is just a suggestion, not everyone will agree with it, and 2D array handling is better in later versions of C. However I think you'll find that this method works best.
hi thanx every body for their support but no one provide me the required information now i try to did that program like this
#include<stdio.h>
#include <stdlib.h>
int main()
{
int **a,i,j;
system("clear");
a=(int*)malloc(sizeof(int)*5);
for (i=0; i<5; i++)
{
a[i]= malloc(sizeof(int)*3);
for (j=0; j<3; j++)
{
printf("\nplease enter the [%d][%d] location = ",i,j);
scanf("%d",&a[i][j]);
}
}
for (i=0; i<5; i++)
{
for (j=0; j<3; j++)
{
printf("\nthe value enter enter the [%d][%d] location = ",i,j);
printf("%d",a[i][j]);
}
}
free(a);
return ;
}
i complied it on compilation it shows warnig which is following
c:8: warning: assignment from incompatible pointer type
on running the program it take 15 value from user but it did not show the value entered by user
can anybody explain what i'm doing wrong ,can any body explain me the concept of double pointer & dynamic memory allocation
This code has several errors. First of all, the warning refers to the fact that you're trying to assign a pointer to integer (int *) to a variable (a) which is a pointer to a pointer to integer (int **), which you actually want to use as an array of arrays.
So, first correction, at line 8 it's not
a=(int*)malloc(sizeof(int)*5);
but it is
a=(int**)malloc(sizeof(int *)*5);
(that cast in C isn't strictly necessary, but being a C++ programmer I prefer to keep it like that)
Notice that also the expression in the sizeof changed, since what you want to allocate is not the space for five integers, but the space for five pointers to integers.
Then, at the end of the application, you're freeing just the space allocated with the first malloc, while you made other five allocations (one for each row). Thus, you could do the deallocation in the last cycle, just after displaying each row.
for (i=0; i<5; i++)
{
for (j=0; j<3; j++)
{
printf("\nthe value enter enter the [%d][%d] location = ",i,j);
printf("%d",a[i][j]);
}
free(a[i]);
a[i]=NULL;
}
free(a);
a=NULL;
Remember: for each malloc or calloc, you have to have it's corresponding free, otherwise you're leaking memory.
Here, after each deallocation, I set the corresponding pointer to NULL to throw away those old, now-invalid, pointers. Somebody say that this behavior can mask double-frees (since free(NULL) doesn't produce errors), but IMHO this is better than the alternative
One important detail: you're not checking the return value of malloc, which is quite bad. It's extremely unlikely that in such small programs allocations may fail, but, nonetheless, it's good practice to always check if the return value of malloc is NULL, and, in this case, handle the situation gracefully, usually releasing all the resources and shutting down the application.
By the way, system("clear"); is ugly. You should use the platform-specific way to clean the screen, even better if enclosed in a function; on Linux with normal (X3.64) terminal emulators something like this could be ok:
void ClearScreen()
{
fputs("\x1B[2J\x1B[1;1H", stdout);
fflush(stdout);
}
Firstly, the memory allocation in your code is incorrect. The first malloc should look as follows
a = (int **) malloc(sizeof(int *) * 5);
Your a is int **, as you declared it. You are casting the result of malloc to int *. int * and int ** are those incompatible types the compiler is warning you about. To avoid such errors in the future, get rid of the bad habit of using types in statements. Types in C belong in declarations. Statements should be as type-independent as possible. The above malloc call would look much better this way
a = malloc(5 * sizeof *a);
Note: no cast, no types mentioned. The second malloc would look as follows
a[i] = malloc(3 * sizeof *a[i]);
I hope you see the pattern in accordance with which these malloc calls are built.
You also forget to deallocate memory for individual sub-arrays in your program (a[i] memory is never deallocated, while a memory is).
As for the program not showing the entered values... The first problem with broken malloc call is serious enough to prevent your program from working, but it still might appear to "work" on some platforms. On such platforms it should show the values. Are you sure you are not simply missing the output?
a points to an array of int pointers. So each element of that array is of type int* not int. So you should be using sizeof(int*).
this
a = (int*)malloc(sizeof(int)*5);
should be
a = malloc(sizeof(int*)*5);
^
As malloc in C returns a void pointer and C implicitly casts from and to void* there is no need of a cast.
You might want to read this:
Should I explicitly cast malloc()'s return value?
a = (int*)malloc(sizeof(int)*5);
^
|
Warning due to this
a is a pointer to pointer to int i.e int **.
You are casting malloc()'s return value to int* and then assigning it to int** so the implicit conversion from int* to int** generates the warning. Moreover it should be sizeof(int *) inside first malloc() [as you are trying to allocate memory for a two dimensional array].
Try this :
a=(int**)malloc(sizeof(int*)*5);
On line 6 you should have
a = (int**) malloc(sizeof(int*) * 5));