2

Allocated a 50*sizeof(int) of dynamic memory using malloc. As I read in some document the immediately below element should be a size of allocated memory using malloc (In my case it is 200 bytes). But when i executed this below code, got 209 instead 200!

    #include<stdio.h>
    #include<malloc.h>
    int main()
    {
        int *p = (int *)malloc(sizeof(int)*50);

        int i;

        for(i = 0; i < 5; i++)
            scanf("%d", &p[i]);

        for(i = -1; i < 5; i++)
            printf(" %d ", *((int *)(p+i)));
        free(p);
    }

Can somebody help whats wrong?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Vijay S B
  • 1,251
  • 1
  • 13
  • 24
  • 1
    Where in your code do you get 209? – Tanner Oct 03 '16 at 12:13
  • Output of first element printed from this snippet---> for(i=-1;i<5;i++) printf(" %d ",*((int *)(p+i))); – Vijay S B Oct 03 '16 at 12:14
  • 2
    [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Oct 03 '16 at 12:14
  • 2
    How malloc does its housekeeping is implementation dependent. Probably some implementation will indeed store the net allocated size just before the first element, but that's up to the authors of the library. What implementation of malloc are you using? – fvu Oct 03 '16 at 12:16
  • @Sourav But Didn't solve my problem – Vijay S B Oct 03 '16 at 12:17
  • @fvu Found this from man page "This page is part of release 3.22 of the Linux man-pages project." – Vijay S B Oct 03 '16 at 12:20
  • @VijaySB Interesting. Can you quote the part of that man page that says this? I have found that exact man page of malloc and it doesn't talk about this (because documenting something so implementation specific would be somewhere between irresponsible and insane). – Art Oct 03 '16 at 12:27
  • @VijaySB that's why that is a comment,not an answer. A ful answer is given below, anyways. – Sourav Ghosh Oct 03 '16 at 12:31

3 Answers3

3

The problem is in the first iteration of

for(i=-1;i<5;i++)
        printf(" %d ",*((int *)(p+i)));

here, the index -1 refers to an invalid memory location and attempt to access that invokes undefined behavior.

FWIW, There is no wrap-around for array indexing in C, it's simple pointer arithmetic and as soon as you point outside the allocated memory region, you hit UB.

That said,

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • If i'm accessing a invalid memory location every time i execute the code, i should get the garbage value right? I'm getting same value every-time – Vijay S B Oct 03 '16 at 12:44
1

This is undefined behavior. You're accessing memory that is outside the region that malloc() returned and this is not valid.

If it was valid in some context, that was an implementation-specific extension and not something you can depend on or do in the general case.

Also, please don't cast the return value of malloc() in C. The printing could just be:

printf(" %d ", p[i]);

the asterisk and cast that you added are not necessary, just use array indexing.

unwind
  • 391,730
  • 64
  • 469
  • 606
1

Tell me the document where you have seen written that the elemnt below malloc()'s return address telles the size of malloc(). I have just read man-page of malloc() but I couldn't find and have never heard of it before. I think you're confused. There's no way to find out the size of dynamically allocated memory unless you keep it.

John Park
  • 1,644
  • 1
  • 12
  • 17
  • "The Linux Programming Interface.pdf" by Michael Kerrisk When malloc() allocates the block, it allocates extra bytes to hold an integer containing the size of the block. This integer is located at the beginning of the block; the address actually returned to the caller points to the location just past this length value, – Vijay S B Oct 03 '16 at 12:27
  • 1
    Vijay S B, I learned more about malloc() thanks to your comment. Now I understand how free() works without telling the size of dinymically allocated by malloc(), and I raised a question that the size of integer must be a long integer if it works on 64bit OS. – John Park Oct 03 '16 at 12:35
  • Thanks for sharing the book "The Linux Programming Interface" by Michael Kerrisk. – Karthik Balaguru Oct 04 '16 at 13:27
  • By the way there's no need to store the length before, or after the allocated memory. You can simply store it elsewhere. So be careful, as **this is a real case of undefined behaviour**. – Luis Colorado Oct 05 '16 at 05:56