Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I can use more memory than how much I've allocated with malloc(), why?

Tags:

c

char *cp = (char *) malloc(1);
strcpy(cp, "123456789");
puts(cp);

output is "123456789" on both gcc (Linux) and Visual C++ Express, does that mean when there is free memory, I can actually use more than what I've allocated with malloc()?

and why malloc(0) doesn't cause runtime error?

Thanks.

like image 878
woongiap Avatar asked Aug 18 '10 07:08

woongiap


People also ask

How much memory can malloc allocate?

The malloc() function reserves a block of storage of size bytes. Unlike the calloc() function, malloc() does not initialize all elements to 0. The maximum size for a non-teraspace malloc() is 16711568 bytes.

Does malloc allocate extra memory?

Because malloc() pads out the memory allocated to multiples of 8 bytes. Thus malloc(4) and malloc(8) allocate 8 bytes for the user, plus an extra 8 bytes for bookkeeping. Malloc(12) and malloc(16) allocate 16 bytes for the user, plus an extra 8 bytes for bookkeeping for a total of 24 bytes.

What happens when malloc Cannot allocate the requested amount of memory?

If the malloc function is unable to allocate the memory buffer, it returns NULL. Any normal program should check the pointers which the malloc function returns and properly handle the situation when the memory allocation failed.

How do I free the memory allocated by malloc?

3.2. 3.3 Freeing Memory Allocated with malloc When you no longer need a block that you got with malloc , use the function free to make the block available to be allocated again. The prototype for this function is in stdlib. h .


4 Answers

You've asked a very good question and maybe this will whet your appetite about operating systems. Already you know you've managed to achieve something with this code that you wouldn't ordinarily expect to do. So you would never do this in code you want to make portable.

To be more specific, and this depends entirely on your operating system and CPU architecture, the operating system allocates "pages" of memory to your program - typically this can be in the order of 4 kilobytes. The operating system is the guardian of pages and will immediately terminate any program that attempts to access a page it has not been assigned.

malloc, on the other hand, is not an operating system function but a C library call. It can be implemented in many ways. It is likely that your call to malloc resulted in a page request from the operating system. Then malloc would have decided to give you a pointer to a single byte inside that page. When you wrote to the memory from the location you were given you were just writing in a "page" that the operating system had granted your program, and thus the operating system will not see any wrong doing.

The real problems, of course, will begin when you continue to call malloc to assign more memory. It will eventually return pointers to the locations you just wrote over. This is called a "buffer overflow" when you write to memory locations that are legal (from an operating system perspective) but could potentially be overwriting memory another part of the program will also be using.

If you continue to learn about this subject you'll begin to understand how programs can be exploited using such "buffer overflow" techniques - even to the point where you begin to write assembly language instructions directly into areas of memory that will be executed by another part of your program.

When you get to this stage you'll have gained much wisdom. But please be ethical and do not use it to wreak havoc in the universe!

PS when I say "operating system" above I really mean "operating system in conjunction with privileged CPU access". The CPU and MMU (memory management unit) triggers particular interrupts or callbacks into the operating system if a process attempts to use a page that has not been allocated to that process. The operating system then cleanly shuts down your application and allows the system to continue functioning. In the old days, before memory management units and privileged CPU instructions, you could practically write anywhere in memory at any time - and then your system would be totally at the mercy of the consequences of that memory write!

like image 120
PP. Avatar answered Oct 02 '22 09:10

PP.


No. You get undefined behavior. That means anything can happen, from it crashing (yay) to it "working" (boo), to it reformatting your hard drive and filling it with text files that say "UB, UB, UB..." (wat).

There's no point in wondering what happens after that, because it depends on your compiler, platform, environment, time of day, favorite soda, etc., all of which can do whatever they want as (in)consistently as they want.

More specifically, using any memory you have not allocated is undefined behavior. You get one byte from malloc(1), that's it.

like image 32
GManNickG Avatar answered Oct 02 '22 08:10

GManNickG


When you ask malloc for 1 byte, it will probably get 1 page (typically 4KB) from the operating system. This page will be allocated to the calling process so as long as you don't go out of the page boundary, you won't have any problems.

Note, however, that it is definitely undefined behavior!

Consider the following (hypothetical) example of what might happen when using malloc:

  1. malloc(1)
  2. If malloc is internally out of memory, it will ask the operating system some more. It will typically receive a page. Say it's 4KB in size with addresses starting at 0x1000
  3. Your call returns giving you the address 0x1000 to use. Since you asked for 1 byte, it is defined behavior if you only use the address 0x1000.
  4. Since the operating system has just allocated 4KB of memory to your process starting at address 0x1000, it will not complain if you read/write something from/to addresses 0x1000-0x1fff. So you can happily do so but it is undefined behavior.
  5. Let's say you do another malloc(1)
  6. Now malloc still has some memory left so it doesn't need to ask the operating system for more. It will probably return the address 0x1001.
  7. If you had written to more than 1 byte using the address given from the first malloc, you will get into troubles when you use the address from the second malloc because you will overwrite the data.

So the point is you definitely get 1 byte from malloc but it might be that malloc internally has more memory allocated to you process.

like image 30
mtvec Avatar answered Oct 02 '22 10:10

mtvec


No. It means that your program behaves badly. It writes to a memory location that it does not own.

like image 26
Didier Trosset Avatar answered Oct 02 '22 08:10

Didier Trosset