444 views

Consider below four program fragments. Which of the program(s) is/are likely to produce run time error or memory leak. Assume malloc is always successful, and sizes are as follows -

sizeof(int *) = 8 bytes
sizeof(double) = 8 bytes
sizeof(char) = 1 byte
sizeof(int) = 4 byte

Program 1
int *array = malloc(n);
for (int i=0; i<n; i+=1) array[i]=i*i;

Program 2
struct p { double x; double y; };
struct p *array = malloc(n * sizeof(struct p *));
for (int i=0; i<n; i+=1) array[i].x=2.3

Program 3
int *p = malloc(sizeof(int));
*p = 42;
p = malloc(sizeof(int));
free(p);

Program 4
void populate(int *a)
{
int *parray = malloc(2 * sizeof(int));
parray = 37;
parray = 73;
a = parray;

}

int main()
{
int *a = NULL;
populate(a);
printf("a = %d and a = %d\n", a, a);
return 0;
}


1. Program $1$
2. Program $2$
3. Program $3$
4. Program $4$

Program 1:

int *array = malloc(n);
for (int i=0; i<n; i+=1) array[i]=i*i;

malloc(n) takes in the number of bytes to be allocated. This allocation would be correct if it was char array but since it is an integer array it requires “n*sizezof(int)”.

Program 2:

struct p { double x; double y; };
struct p *array = malloc(n * sizeof(struct p *));
for (int i=0; i<n; i+=1) array[i].x=2.3

Let “ptr is a pointer to pointer to int”: int **ptr; Then the types of *ptr (de-referenced pointer) and int * (type of pointer) are same. Because the *ptr (de-referenced pointer) points to the object of type int *.

Here if the statement was “n * sizeof(struct p)” then the snippet would be correct.

Program 3:

int *p = malloc(sizeof(int));
*p = 42;
p = malloc(sizeof(int));
free(p);

Line 1 is correct. The thing that should be taken care of is *p and p.

Line 2 basically saves into that heap allocated memory the value 42, so it is also correct.

Line 3 however allocated some new memory and saves it to the same pointer, now the reference/pointer to the old memory (where 42 is written) is lost: Memory leak.

Program 4: This one’s my favorite among all. I have changed the local int pointer a in the populate() to p

void populate(int *p)
{
int *parray = malloc(2 * sizeof(int));
parray = 37;
parray = 73;
p = parray;
}
int main()
{
int *a = NULL;
populate(a);
printf("a = %d and a = %d\n", a, a);
return 0;
}

A quick way to avoid mistakes is to rename local variables if they are same as any other to avoid confusion while solving. Especially in pointers.

Just as the operating system would, let’s start form main. a is the pointer to an int. which is set to NULL.

The populate() gets the VALUE of a (which is currently NULL) it does not get the address of the pointer.

whatever populate() does with it’s local variable a (which I changed to p) can never reflect back in main(). So the memory which local pointer variables parray and p were pointing to is no longer being pointed at because both parray and p were deleted when the populate() returned, hence memory leak.

Further in the main() executing a will raise a runtime error because variable a is pointing to NULL and by executing a we are effectively de-referencing it which is illegal.

@Yuvraj Raghuvanshi, yes correct. Hardcoding things like these is not a good practice. But here I was just trying to understand how int *myArr is interpreting the memory allocated to it.

Program 4 showing both runtime error and memory leak.

Yes that’s natural. You can’t de-reference a null pointer. I will update the answer.