-2

After reading tutorials, I adopted a way to create 2-D array with malloc. But to my surprise, changing allocation code with many variants, gives me the same output.

Consider:

#include<stdio.h>
#include<conio.h>
void main()
{

int **ptr;

int row=3,col=5,i,j;

*ptr=(int **) malloc(sizeof(int *));

for(i=0;i<3;i++)
{

ptr[i]=(int *) malloc(sizeof(int )*col);

}


for(i=0;i<row;i++)
{

for(j=0;j<col;j++)
  {
ptr[i][j]=1;

  }
}


for(i=0;i<row;i++)
{

   for(j=0;j<col;j++)
  {
   printf("val %d",ptr[i][j]);
   free(ptr[i][j]);
  }
printf("\n");
}


free(ptr);

getch();
}

(sorry for an old compiler-turboc 3 , its a compulsion)

when the statement :

*ptr=(int **) malloc(row*col*sizeof(int *));

is changed to

*ptr=(int **) malloc(sizeof(int *));

or to

*ptr=(int *) malloc(sizeof(int *));

or

*ptr=(int ) malloc(sizeof(int *));

or

*ptr=(int **) malloc(row*sizeof(int *));

....

GIVES me the same output, that is an array of 3*4 with all 1's.

Why is is so?

joey rohan
  • 3,505
  • 5
  • 33
  • 70
  • Please format your code in a readable way. – m0skit0 Dec 09 '13 at 15:42
  • 1
    No 2D arrays here. Only a pointer-to-pointer. And `malloc()`'s return value is [not to be cast](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858). –  Dec 09 '13 at 15:44
  • 1
    are you **sure** deep inside your soul that malloc(4) is the same as malloc(4000)? Really? BTW you're playing with useless casts too (with conversions allowed just because of your compiler). malloc results shouldn't b e casted (ignoring other errors too...) – Adriano Repetti Dec 09 '13 at 15:45
  • It is an area that has not been secured `*ptr`. – BLUEPIXY Dec 09 '13 at 15:45
  • 1
    Don't cast the return of malloc in C please. – Gabson Dec 09 '13 at 15:46
  • That's all error when you are using it to dereference a pointer to pointer that has not been initialized. – BLUEPIXY Dec 09 '13 at 16:01

2 Answers2

1

Malloc allocate a space defined by the size you give to. But when you copy some charracters if there is enought place on the RAM it will works even if you specified a smaller size than the string you wanted to copy. In the other case, it will print random characters, or Glibc - memory corrupted. So even if all these malloc definitions works, maybe it works on your computer "for the moment". But on an other and in other case it won't at all. Moreover Glibc is dangerous.

Gabson
  • 421
  • 1
  • 4
  • 20
  • May be the commentators thought I am playing a-fool-game with them.Anyways, what about casting it to `(int *)` and `(int **)` give same stuff? Also, any links/documentation for above answer ? – joey rohan Dec 09 '13 at 15:53
  • maybe `sizeof(int *)` == `sizeof(int **)`; I think both pointers have the same size. If they do not, then its still cause malloc allocate that "free more space" – Gabson Dec 09 '13 at 15:58
1

In an attempt to be a litte bit more efficient, malloc typically assigns a "minimum block of space". This might be 16 bytes, or more - depending on the compiler. I think you are "accidentally" getting a big enough block - capable of seeing 12 ints - without getting a error. But your code is highly suspect and liable to break at any time.

As @H2CO3 pointed out - don't cast the return value of malloc: if your compiler is complaining you didn't include the right headers. Always heed your compiler's warnings - but address them in the right way...

Note - it's not the malloc that gives you the array of ones - that's the job of the loop that follows. malloc sets aside some space. If it sets aside enough space you won't run into a segfault. It does nothing to affect how the compiler considers that piece of memory subsequently. In other words - malloc does not know what it returns (which is why the type is actually void* and you should not cast it).

EDIT you were asking about the different casting you did. A cast does not change the VALUE, just the TYPE (as long as the value can be represented with the new type). Thus, when you say

int* p;
p = (int **)malloc(4);

you are not turning p into a int** - its type was defined by the first line. You will (or should) get some compiler warnings...

Floris
  • 45,857
  • 6
  • 70
  • 122
  • See some helpful information about the minimum allocation, alignment, etc at http://prog21.dadgum.com/179.html . – Floris Dec 09 '13 at 15:59
  • Well, no compiler warnings. Can the return value of `malloc` be different for old compilers? In the documentation of `Turbo C`, in their very own example, the have cast the return of `malloc`. – joey rohan Dec 09 '13 at 16:04
  • I just cracked open my "old" K&R (2nd edition, 1988). It states (section 6.5, p 142) "In C, the proper method is to declare that `malloc` returns a pointer to `void`, then explicitly coerce the pointer into the desired type with a cast." And that's probably where Turbo C got it. But casting (int**) and assigning to `int*` should generate a warning, regardless. Maybe it's time to upgrade your compiler (and start using a more modern version of C). – Floris Dec 09 '13 at 16:24
  • running the same on linux, gives me hell lot of seg. faults n stuff.Well, I was hell lot of surprised today. thanks. – joey rohan Dec 09 '13 at 16:34
  • 1
    At least it shows you have not completely lost your mind - you were just being misled by an obsolete compiler. I hope that was a pleasant surprise? Glad I was able to help a little. – Floris Dec 09 '13 at 16:40