c -language dynamic memory - c

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));

Related

Runtime errors vs memory leak vs linkedit error

My teacher gave us a piece of code as homework and asked us what is the kind of error.
I don't really know what errors exist so that's why I'm asking here.
#include <stdio.h>
int main()
{
int m, n;
scanf("%d%d", &m, &n);
int i, ** a;
a = (int**)malloc(m * sizeof(int*));
for (i = 0; i < m; i++)
{
a[i] = (int*)malloc(n * sizeof(int));
}
free(a[0]);
free(a);
return 0;
}
It is either a runtime error, a memory leak, or a linkedit error.
Can anybody help me classify this error and also help me understand the difference between these types of errors?
Thanks.
It is a memory leak for any m > 1. To avoid it you need to free all "malloced" memory.
In your code first is allocated space for m pointers to int. Then it allocates m memory blocks having the size of n integers.
You free only 2 memory blocks. The second return frees the memory where pointers to allocated blocks are kept. Access to them is lost and this memory cannot be accessed to freed anymore - thus "memory leak"
BTW if it is the code given by the teacher then it shows that he needs to start to read SO to learn some stuff about the C language (or even better read an up to date book about this language).
main What are the valid signatures for C's main() function?
he should check the return value of scanf. He should check if the scanned values make any sense.
He should use the correct type for sizes and indexes it is size_t
He should not cast the result of malloc
He should use objects instead of types in sizeof
He does not include stdlib.h required to use malloc & free.
Quite a lot issues in the 10 lines C programm.

Having a little trouble understanding memory allocation in C

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.

Allocating 2D array of dimensions read from file

I would like to read 2 numbers n,m from text file and then allocate a 2D array with n rows and m columns.
Also, I would like to initialise the array in my main function in order to use it later in other functions, and do the reading and allocating in a different function, which I will call from the main function.
I know how to handle the reading, but I'm struggling with the array allocation.
I've read quite a few answer to similar questions here, but they didn't help me.
I've wrote the following code, but not sure how to continue with it to get the desired result:
void func(int** array, int* rows, int* cols){
int n, m;
FILE *file;
fp = fopen("test.txt", "r");
if (file) {
/* reading numbers n and m */
*rows = n;
*cols = m;
**array = (int*)malloc(n * m * sizeof(int));
fclose(file);
}
}
int main() {
int rows, cols;
int** array;
func(&array, &rows, &cols);
return 0;
}
I thought perhaps I should first allocate a 2D array with calloc and then use realloc after reading n,m, but not sure if that's the best practise.
What is the best practise to allocate a 2D array based on dimensions I read from text file?
First the biggest goofs here:
Your function doesn't have any types in the function signature -- this should be rejected by the compiler
a 2D array is not the same as an array of pointers
what should && mean? & is the address of something, its result can't have an address because it isn't stored anywhere, so this doesn't make sense
If you want to dynamically allocate a real 2D array, you need to either have the second dimension fixed or use VLAs (which are optional in C11, but assuming support is quite safe) with a variable. Something like this:
// dimensions in `x` and `y`, should be of type `size_t`
int (*arr)[x] = malloc(y * sizeof *arr);
In any case, the second dimension is part of the type, so your structure won't work -- the calling code has to know this second dimension for passing a valid pointer.
Hint: This first part doesn't apply to the question any more, OP forgot to mention he's interested in C90 only. I added the appropriate tag, but leave the upper part of the answer for reference. The following applies to C90 as well:
You write int ** in your code, this would be a pointer to a pointer. You can create something that can be used like a 2D array by using a pointer to a pointer, but then, you can't allocate it as a single chunk.
The outer pointer will point to an array of pointers (say, the "row-pointers"), so for each of these pointers, you have to allocate an array of the actual values. This could look like the following:
// dimensions again `x` and `y`
int **arr = malloc(y * sizeof *arr);
for (size_t i = 0; i < y; ++i)
{
arr[i] = malloc(x * sizeof **arr);
}
Note on both snippets these are minimal examples. For real code, you have to check the return value of malloc() each time. It could return a null pointer on failure.
If you want to have a contiguous block of memory in the absence of VLAs, there's finally the option to just use a regular array and calculate indices yourself, something like:
int *arr = malloc(x * y * sizeof *arr);
// access arr[8][15] when x is the second dimension:
arr[x*8 + 15] = 24;
This will generate (roughly) the same executable code as a real 2D array, but of course doesn't look that nice in your source.
Note this is not much more than a direct answer to your immediate question. Your code contains more goofs. You should really enable a sensible set of compiler warnings (e.g. with gcc or clang, use -Wall -Wextra -pedantic -std=c11 flags) and then fix each and every warning you get when you move on with your project.

Malloc(0)ing an array in Windows Visual Studio for C allows the program to run perfectly fine

The C program is a Damereau-Levenshtein algorithm that uses a matrix to compare two strings. On the fourth line of main(), I want to malloc() the memory for the matrix (2d array). In testing, I malloc'd (0) and it still runs perfectly. It seems that whatever I put in malloc(), the program still works. Why is this?
I compiled the code with the "cl" command in the Visual Studio developer command prompt, and got no errors.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main(){
char y[] = "felkjfdsalkjfdsalkjfdsa;lkj";
char x[] = "lknewvds;lklkjgdsalk";
int xl = strlen(x);
int yl = strlen(y);
int** t = malloc(0);
int *data = t + yl + 1; //to fill the new arrays with pointers to arrays
for(int i=0;i<yl+1;i++){
t[i] = data + i * (xl+1); //fills array with pointer
}
for(int i=0;i<yl+1;i++){
for(int j=0;j<xl+1;j++){
t[i][j] = 0; //nulls the whole array
}
}
printf("%s", "\nDistance: ");
printf("%i", distance(y, x, t, xl, yl));
for(int i=0; i<yl+1;i++){
for(int j=0;j<xl+1;j++){
if(j==0){
printf("\n");
printf("%s", "| ");
}
printf("%i", t[i][j]);
printf("%s", " | ");
}
}
}
int distance(char* y, char* x, int** t, int xl, int yl){
int isSub;
for(int i=1; i<yl+1;i++){
t[i][0] = i;
}
for(int j=1; j<xl+1;j++){
t[0][j] = j;
}
for(int i=1; i<yl+1;i++){
for(int j=1; j<xl+1;j++){
if(*(y+(i-1)) == *(x+(j-1))){
isSub = 0;
}
else{
isSub = 1;
}
t[i][j] = minimum(t[i-1][j]+1, t[i][j-1]+1, t[i-1][j-1]+isSub); //kooks left, above, and diagonal topleft for minimum
if((*(y+(i-1)) == *(x+(i-2))) && (*(y+(i-2)) == *(x+(i-1)))){ //looks at neighbor characters, if equal
t[i][j] = minimum(t[i][j], t[i-2][j-2]+1, 9999999); //since minimum needs 3 args, i include a large number
}
}
}
return t[yl][xl];
}
int minimum(int a, int b, int c){
if(a < b){
if(a < c){
return a;
}
if(c < a){
return c;
}
return a;
}
if(b < a){
if(b < c){
return b;
}
if(c < b){
return c;
}
return b;
}
if(a==b){
if(a < c){
return a;
}
if(c < a){
return c;
}
}
}
Regarding malloc(0) part:
From the man page of malloc(),
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
So, the returned pointer is either NULL or a pointer which can only be pasxed to free(), you cannot expect to dereference that pointer and store something into the memory location.
In either of the above cases, you're trying to to use a pointer which is invalid, it invokes undefined behavior.
Once a program hits UB, the output of that cannot be justified anyway.
One of the major outcome of UB is "working fine" (as "wrongly" expected), too.
That said, follwing the analogy
"you can allocate a zero-sized allocation, you just must not dereference it"
some of the memory debugger applications hints that usage of malloc(0) is potentially unsafe and red-zones the statements including a call to malloc(0).
Here's a nice reference related to the topic, if you're interested.
Regarding malloc(<any_size>) part:
In general, accessing out of bound memory is UB, again. If you happen to access outside the allocated memory region, you'll invoke UB anyways, and the result you speculate cannot be defined.
FWIW, C itself does not impose/ perform any boundary checking on it's own. So, you're not "restricted" (read as "compiler error") from accessing out of bound memory, but doing so invokes UB.
It seems that whatever I put in malloc(), the program still works. Why is this?
int** t = malloc(0);
int *data = t + yl + 1;
t + yl + 1 is undefined behavior (UB). Rest of code does not matter.
If t == NULL, adding 1 to it is UB as adding 1 to a null pointer is invalid pointer math.
If t != NULL, adding 1 to it is UB as adding 1 to that pointer is more than 1 beyond the allocating space.
With UB, the pointer math may worked as hope as typical malloc() allocates larges chunks, not necessarily the small size requested. It may crash on another platform/machine or another day or phase of the moon. The code is not reliable even if it works with light testing.
You just got lucky. C does not do rigorous bounds checking because it has a performance cost. Think of a C program as a raucous party happening in a private building, where the OS police are stationed outside. If somebody throws a rock that stays inside the club (an example of an invalid write that violates the ownership convention within the process but stays within the club boundaries) the police don't see it happening and take no action. But if the rock is thrown and it goes flying dangerously out the window (an example of a violation that is noticed by the operating system) the OS police step in and shut the party down.
The C standard says:
If the size of the space requested is zero, the behavior is implementation-defined; the value returned shall be either a null pointer or a unique pointer. [7.10.3]
So we have to check what your implementation says. The question says "Visual Studio," so let's check Visual C++'s page for malloc:
If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item.
So, with Visual C++, we know that you're going to get a valid pointer rather than a null pointer.
But it's just a pointer to a zero-length item, so there's not really anything safe you can do with that pointer except pass it to free. If you dereference the pointer, the code is allowed to do anything it wants. That's what's meant by "undefined behavior" in the language standards.
So why does it appear to work? Probably because malloc returned a pointer to at least a few bytes of valid memory since the easiest way for malloc to give you a valid pointer to a zero-length item is to pretend you really asked for at least one byte. And then the alignment rules would round that up to something like 8 bytes.
When you dereference the beginning of that allocation, you likely have some valid memory. What you're doing is strictly illegal, non-portable, but, with this implementation, likely to work. When you index farther into it, you'll likely start corrupting other data structures (or metadata) in the heap. If you index even father into it, you're increasingly likely to crash due to hitting an unmapped page.
Why does the standard allow malloc(0) to be implementation-defined instead of just requiring it to return a null pointer?
With pointers, it's sometimes hand to have special values. The most obvious being the null pointer. The null pointer is just a reserved address that will never be used for valid memory. But what if you wanted another special pointer value that had some meaning to your program?
In the dark days before the standard, some mallocs allowed you to effectively reserve additional special pointer values by calling malloc(0). They could have used malloc(1) or any other very small size, but malloc(0) made it clear that you just wanted to reserve and address rather than actual space. So there were many programs that depended on this behavior.
Meanwhile, there were programs that expected malloc(0) to return a null pointer, since that's what their library had always done. When the standards people looked at the existing code and how it used the library, they decided they couldn't choose one method over the other without "breaking" some of the code out there. So they allowed malloc's behavior to remain "implementation-defined."

Multidimensional array with unequal second dimension size using malloc()

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.

Resources