0

I wrote this program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct inventory{
    int ID;
    char name[20];
    int value;
};


int main()
{
    struct inventory *inv;

    inv = malloc(sizeof(1));

    inv[0].ID = 10;
    strcpy(inv[0].name,"hello charlie old mate");
    inv[0].value = 20;

    inv[1].ID = 20;

    printf("%d", inv[1].ID);

    return 0;
   }

Can you tell me how can inv[1].ID be set up to 20. When I allocated just 1 byte of memory for inv. How can it carry data of multiple structures?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 2
    Have you ever heard about *undefined behavior*? – haccks May 17 '16 at 19:14
  • 1
    " When i allocated just 1 byte of memory for inv. " is false. Code allocated `sizeof(1)` bytes which is certainly not 1, but more likely 4. – chux - Reinstate Monica May 17 '16 at 19:22
  • 1
    just to elaborate what @chux sir said, `sizeof` considers the data type, not the _value_, a literal `1` is of type `int`. :) – Sourav Ghosh May 17 '16 at 19:24
  • 1
    "I paid for one parking space, but then I parked lots of cars on that space and some adjacent ones. How can that be? I only paid for one space." – Thomas Padron-McCarthy May 17 '16 at 19:24
  • 1
    @ThomasPadron-McCarthy let me know whether you are able to find your car there tomorrow morning. :) – Sourav Ghosh May 17 '16 at 19:25
  • 1
    @SouravGhosh: When I came back next day, some of my cars had been towed, some had been stolen, and someone had parked a truck on top of one of them so it was flat! Only the one on the parking sport I paid for was still there! Actually, I could turn this into a nice answer about undefined behavior, but someone already did that: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794 – Thomas Padron-McCarthy May 17 '16 at 19:28
  • 1
    @ThomasPadron-McCarthy did you forget to mention that the _legit_ one was having scratches all over it due to the towing process? – Sourav Ghosh May 17 '16 at 19:30
  • 1
    I thought you weren't allowed to run with the ball in basketball, but I tried it and it worked. what is going on and why did the other players get angry? – M.M May 17 '16 at 22:24

2 Answers2

3

There is undefined behaviour in your code -

inv = malloc(sizeof(1));      // you allocate size of int
inv[0].ID = 10;
strcpy(inv[0].name,"hello charlie old mate");    //copying more than your buffer can hold

You allocate size equal to that of int and is not enough for structure and access unauthorized memory.And then the strcpy, you try to store more contents than the space available. name can contain 19 characters and '\0' at end. And the string you copy is larger then 19 characters.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
1

Can you tell me how can inv[1].ID be set up to 20. When I allocated just 1 byte of memory for inv. How can it carry data of multiple structures?

TL;DR It cannot.

What you're seeing is invalid access of memory which invokes undefined behavior. There is nothing in C standard that prevents you from from writing a code accessing invalid memory, but as soon as you do that, voila!!

The memory allocated to inv (by calling malloc(1)) is way less then it should be. Thus, basically, you're trying to access memory that does not belong to you (your process) and hence that memory is invalid. Any attempt to access invalid memory results in UB.

Following the same trail, even after you have allocated proper memory for inv, then also

 strcpy(inv[0].name,"hello charlie old mate");

will be UB, as you're trying to copy more than 20 elements into the destination having only size of 20 (which can hold 19 valid chars + 1 null terminator, if you want name to be used as a string). Count your memory requirement properly and stay within bounds.

That said, always check for the return value of malloc() for success before using the returned pointer.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • I do know what u mean i shout allocate inv = malloc(sizeof(struct inventory)); So it should make the pointer access just one struct inv[0] though even when i add more to inv[1],(...) inv[5] it compiles and gives certainly some strange answers. Look my comment to the top with a prtscr – Fenixx Reborn May 17 '16 at 19:26
  • 3
    @FenixxReborn Yes, or. for better, `inv = malloc(sizeof *inv);` – Sourav Ghosh May 17 '16 at 19:26
  • @FenixxReborn for the edited part, you __must__ know the size of allocation and access accordingly. Again, C won't stop you from accessing `inv[5]` while you';re allocated only for 1 element, but it will lead to UB. – Sourav Ghosh May 17 '16 at 19:29
  • I added values just to some of the struct parts. It attached 0 to all of them. Without any initialization. This is strange, don't understand this at all. As there should be garbage as i think? The UB doesnt yeld bad results by accessing this memory. Though, when i create more valid data in my program it could be taken by that, right? So finally when i want to create a valid pointer array to structures i should realloc them by n * sizeof(struct inventory) and then i can call them by the calls inv[1] and inv[2]. Am i right? – Fenixx Reborn May 17 '16 at 19:35
  • @FenixxReborn basically yes. But keep in mind, `malloc()` returns unitialized memory, the content in indeterminate. and yes, `0` is very much a garbage value (in this context), just like `4537921636` or `-62490936` – Sourav Ghosh May 17 '16 at 19:38
  • Thanks. I was certailny dumb. Though the formated 0 output for like 20 structures i printed. Made me think of it could initialize it somehow. Now im sure its just luky garbage. Saved my evening sir. – Fenixx Reborn May 17 '16 at 19:44
  • @FenixxReborn Happy it helped. :) – Sourav Ghosh May 17 '16 at 19:46