-3

#include<stio.h>
main()
{
  int *p,i;
  p = (int*)malloc(sizeof(int));
  printf("Enter:");
  scanf("%d",p);
  for(i=1;i<3;i++)
  {
   printf("Enter");
   scanf("%d",p+i);
  }

  for(i=0;i<3;i++)
  {
    printf("No:%d\n",*(p+i));
  }
  getch();
  return 0;
}

In this C program memory is accessed without allocation.The program works.Will any problem arise by accessing memory without allocation?If yes then what is the solution for storing a collection of integer data which the size is not known in advance?

Siva Sankaran
  • 2,407
  • 2
  • 15
  • 4
  • 1
    My inner grouch wants me to add: Did you *read* the manual? If it were ok, why would `malloc()` *need* a parameter to specify the size? Why would you even expect this to work? – RBerteig Aug 19 '10 at 07:04
  • When you say the program "works", what do you mean? Do you mean it does what you expect it to do? If so, what do you expect it to do and why? – David Schwartz Nov 28 '16 at 11:25
  • 1
    Your code exhibits undefined behaviour, because `p` has an allocated size of one `int`, but is being used as if it is an array of four `int`. When behaviour is undefined, any result is possible. The fact it seems to work (whatever you mean by that) is meaningless. It might work, it might not work, depending on how you test it. It might even work every second day, and not work on other days. Any result you get - whether you think it works or not - is possible. – Peter Jun 17 '17 at 06:00

6 Answers6

8

Yes, it leads to undefined behavior. The problem is working here purely becuase of luck and may crash any time. The solution is to allocate the memory using malloc For example if you want to allocate memory for count number of elements then you can use int* p = (int*)malloc(sizeof(int)*count);. From here on you can access p as an array of count elements.

Naveen
  • 74,600
  • 47
  • 176
  • 233
  • 4
    And I'd say it is **bad luck** that it appears to work. Crash early, loudly, and often as my mentor used to say. – RBerteig Aug 19 '10 at 07:02
3

It likely works because the memory immediately after *p is both accessible (allocated in the VM system and has the right bits set), and not in use for anything else. This could all change if malloc finds you some bytes immediately before an inaccessible page; or if you move to a malloc implementation that uses the trailing space for bookkeeping.

So it's not really safe.

Edmund
  • 10,533
  • 3
  • 39
  • 57
1

The reason this code works is that the kernel never gives you a fraction of the system page size (which should be 4k). This means the memory after the first sizeof(int) bytes is actually owned by the process you run, but not allocated to you by the second layer of abstraction which is malloc.

"Segmentation fault" happens when you try and access memory outside the pages allocated to you by the kernel. You won't see it until you step out of your page.

The problem that may arise here is that you use malloc again and you will receive a pointer to a memory you used without malloc being aware of it. This will cause hellish bugs since you will change data used in different contexts without knowing.

As for your second question, the right way is very program dependent.

If the number of elements can be bounded reasonably, it might be OK to always allocate the same size using a constant defined in your program. This is ALWAYS the secure way (you need to make sure you don't let the user give you more than what you allocated).

If you really have a broad range of array sizes here, you might want to use a linked list which is built for that exactly.

Ben Danon
  • 176
  • 1
  • 1
  • 11
1

Accessing unallocated memory leads to undefined behavior. Exactly what happens will depends on a variety of conditions. It may "work" now but you could see problems when you extend your program.

If you don't know how many items you want to read, there are a couple of strategies to use.

  1. Use realloc to grow the buffer as you need more space.
  2. Use a linked list instead of an array
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
1

Most definitely yes. Its just pure luck that you can access without allocating. malloc does not what memory you are using and that could result in serious problems.

Hence its a compulsion (i don't want to use the word better here) to allocate memory according to your needs and then use it.

Some problems which could result are:

  1. Segmentation fault
  2. Memory corruption

and it may result in giving you headache for hours when the behavior is undefined. For eg: the location of a crash may not be the exact place of origin of the problem.

Praveen S
  • 10,355
  • 2
  • 43
  • 69
0

There are two levels of memory allocation that take usually take place. At operating system level, you map memory pages to your address space. A page is the basic unit of memory management and is usually something like 1K or 4K bytes (but can be much larger or as small as 512 bytes, depending upon the system). It is possible to do that mapping yourself by making the appropriate system calls. However, applications generally only do that when they need large blocks of memory.

Standard libraries generally maintain a pool of pages. When you call malloc, the library looks to see if there is available memory in the pool. If so, it returns a block of memory from pages already mapped by the operating system. If not, the library make the system call to map more pages to the process and adds them to the managed pool.

Mapping and unmapping pages is a rather time consuming process. By using pooling, the library can speed things up significantly.

Invariable, the standard library functions allocate a few bytes in front of the memory returned by malloc and the like so that they can know how much memory is in the block when it is free'd. Many will also add memory add the end of the block as well for error checking.

When you are doing what you are doing, you could be reading this extra data or you could be reading some data that was mapped to the memory pool by the library.

What you are doing is bad.

IF you do not know the number of items in advance, you can use a data structure, such a linked list where new entries are created with each new number.

user3344003
  • 20,574
  • 3
  • 26
  • 62