I'm working on a homework assignment that requires me to write a program that leaks memory, keep track of how much memory it is leaking until it crashes.
My general thoughts for the program would be to continuously reassign a malloc pointer.
Here's my code so far:
char *oldMemory = malloc(125000); //1MB of memory.
char *newMemory = malloc(125000);
oldMemory = newMemory;
Is there are way to put this in a loop and repeatedly orphan a
certain amount of memory until the program can no longer allocate any memory and crashes?
How can I keep track of how much memory was leaked before the program crashed?
Thanks for your time and expertise!
Yes.
Count the size of the leaked allocations.
Don't forget to print the size leaked on each iteration - so you see the result even if the program crashes. The program should not crash if you test for failed allocations before accessing it.
Hence:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
enum { ALLOCSIZE = 125000 };
int main(void)
{
long long size = 0;
char *space = malloc(ALLOCSIZE);
while (space != 0)
{
size += ALLOCSIZE;
printf("OK %lld\n", size);
memset(space, '\0', ALLOCSIZE);
}
return(0);
}
The Linux OOM might confuse things; it allows over-commitment of memory. You'd have to access the allocated memory before leaking it - hence the memset() (or you could use calloc() instead of malloc()).
when you allocate some block of memory in C you should be responsible to free it using
free() function.
if you want to make sure that your program won't crash due to some memory leaks.
you can use assert() function when asking for more memory or using the allocated memory.
and you should check on the returned pointer returned from malloc , if it's NULL so the allocation failed. >> Be careful in linux kernels malloc() won't return NULL ever,due to "memory overcommit"
Related
I am fairly new to C. I am currently learning about memory leaks, and I am trying to create one with a simple C program. I am supposed to run the until it crashes, but when I run it, the memory used peaks at around 95%. Is my code not a memory leak? Is it possible with paging on?
Here is the code that I am trying:
int main(void) {
while (1)
{
char *newArea = malloc(10);
char *mainArea = malloc(10000);
mainArea = newArea;
}
}
In order to make programs faster and less memory consuming, many OS don't allocate any dynamic memory before the point where you actually use it. Your code never uses the dynamic memory, so the OS probably does not allocate anything, it just reserves that memory.
So if you just try to write somewhere inside the allocated memory, you should run out of memory as expected, as you will then force the OS to perform the actual allocation.
What you do is just exhausting the available memory, and you can do that simpler – just allocate memory and forget it:
int main(void)
{
while (1)
{
(void) malloc(10000);
}
return 0; // will never get here!
}
Memory leak, however, is something else – it is allocating memory for some task and not disposing it after. For example:
int main(void)
{
while (StillSomethingToDo())
{
char *membuffer = malloc(10000);
DoSomethingWithTheBuffer(membuffer);
// forget to free(membuffer)
}
return 0; // will return normally
}
After the loop terminates when StillSomethingToDo() returns 'false' the main() proceeds to return, however there are some blocks on the heap (lots of them, possibly) which were not free-d. And they can't be freed anymore, because the pointers to them (all the previous values of membuffer variable) are lost.
int a = 0;
int *b = malloc (sizeof(int));
b = malloc (sizeof(int));
The above code is bad because it allocates memory on the heap and then doesn't free it, meaning you lose access to it. But you also created 'a' and never used it, so you also allocated memory on the stack, which isn't freed until the scope ends.
So why is it bad practice to not free memory on the heap but okay for memory on the stack to not be freed (until the scope ends)?
Note: I know that memory on the stack can't be freed, I want to know why its not considered bad.
The stack memory will get released automatically when the scope ends. The memory allocated on the heap will remain occupied unless you release it explicitly. As an example:
void foo(void) {
int a = 0;
void *b = malloc(1000);
}
for (int i=0; i<1000; i++) {
foo();
}
Running this code will decrease the available memory by 1000*1000 bytes required by b, whereas the memory required by a will always get released automatically when you return from the foo call.
Simple: Because you'll leak memory. And memory leaks are bad. Leaks: bad, free: good.
When calling malloc or calloc, or indeed any *alloc function, you're claiming a chunk of memory (the size of which is defined by the arguments passed to the allocating function).
Unlike stack variables, which reside in a portion of memory the program has, sort of, free reign over, the same rules don't apply to heap memory. You may need to allocate heap memory for any number of reasons: the stack isn't big enough, you need an array of pointers, but have no way of knowing how big this array will need to be at compile time, you need to share some chunk of memory (threading nightmares), a struct that requires the members to be set at various places (functions) in your program...
Some of these reasons, by their very nature, imply that the memory can't be freed as soon as pointer to that memory goes out of scope. Another pointer might still be around, in another scope, that points to the same block of memory.
There is, though, as mentioned in one of the comments, a slight drawback to this: heap memory requires not just more awareness on the programmers part, but it's also more expensive, and slower than working on the stack.
So some rules of thumb are:
You claimed the memory, so you take care of it... you make sure it's freed when you're done playing around with it.
Don't use heap memory without a valid reason. Avoiding stack overflow, for example, is a valid reason.
Anyway,
Some examples:
Stack overflow:
#include <stdio.h>
int main()
{
int foo[2000000000];//stack overflow, array is too large!
return 0;
}
So, here we've depleted the stack, we need to allocate the memory on the heap:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *foo= malloc(2000000000*sizeof(int));//heap is bigger
if (foo == NULL)
{
fprintf(stderr, "But not big enough\n");
}
free(foo);//free claimed memory
return 0;
}
Or, an example of an array, whose length depends on user input:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *arr = NULL;//null pointer
int arrLen;
scanf("%d", &arrLen);
arr = malloc(arrLen * sizeof(int));
if (arr == NULL)
{
fprintf(stderr, "Not enough heap-mem for %d ints\n", arrLen);
exit ( EXIT_FAILURE);
}
//do stuff
free(arr);
return 0;
}
And so the list goes on... Another case where malloc or calloc is useful: An array of strings, that all might vary in size. Compare:
char str_array[20][100];
In this case str_array is an array of 20 char arrays (or strings), each 100 chars long. But what if 100 chars is the maximum you'll ever need, and on average, you'll only ever use 25 chars, or less?
You're writing in C, because it's fast and your program won't use any more resources than it actually needs? Then this isn't what you actually want to be doing. More likely, you want:
char *str_array[20];
for (int i=0;i<20;++i) str_array[i] = malloc((someInt+i)*sizeof(int));
Now each element in the str_array has exactly the amount of memory I need allocated too it. That's just way more clean. However, in this case calling free(str_array) won't cut it. Another rule of thumb is: Each alloc call has to have a free call to match it, so deallocating this memory looks like this:
for (i=0;i<20;++i) free(str_array[i]);
Note:
Dynamically allocated memory isn't the only cause for mem-leaks. It has to be said. If you read a file, opening a file pointer using fopen, but failing to close that file (fclose) will cause a leak, too:
int main()
{//LEAK!!
FILE *fp = fopen("some_file.txt", "w");
if (fp == NULL) exit(EXIT_FAILURE);
fwritef(fp, "%s\n", "I was written in a buggy program");
return 0;
}
Will compile and run just fine, but it will contain a leak, that is easily plugged (and it should be plugged) by adding just one line:
int main()
{//OK
FILE *fp = fopen("some_file.txt", "w");
if (fp == NULL) exit(EXIT_FAILURE);
fwritef(fp, "%s\n", "I was written in a bug-free(?) program");
fclose(fp);
return 0;
}
As an asside: if the scope is really long, chances are you're trying to cram too much into a single function. Even so, if you're not: you can free up claimed memory at any point, it needn't be the end of the current scope:
_Bool some_long_f()
{
int *foo = malloc(2000000000*sizeof(int));
if (foo == NULL) exit(EXIT_FAILURE);
//do stuff with foo
free(foo);
//do more stuff
//and some more
//...
//and more
return true;
}
Because stack and heap, mentioned many times in the other answers, are sometimes misunderstood terms, even amongst C programmers, Here is a great conversation discussing that topic....
So why is it bad practice to not free memory on the heap but okay for memory on the stack to not be freed (until the scope ends)?
Memory on the stack, such as memory allocated to automatic variables, will be automatically freed upon exiting the scope in which they were created.
whether scope means global file, or function, or within a block ( {...} ) within a function.
But memory on the heap, such as that created using malloc(), calloc(), or even fopen() allocate memory resources that will not be made available to any other purpose until you explicity free them using free(), or fclose()
To illustrate why it is bad practice to allocate memory without freeing it, consider what would happen if an application were designed to run autonomously for very long time, say that application was used in the PID loop controlling the cruise control on your car. And, in that application there was un-freed memory, and that after 3 hours of running, the memory available in the microprocessor is exhausted, causing the PID to suddenly rail. "Ah!", you say, "This will never happen!" Yes, it does. (look here). (not exactly the same problem, but you get the idea)
If that word picture doesn't do the trick, then observe what happens when you run this application (with memory leaks) on your own PC. (at least view the graphic below to see what it did on mine)
Your computer will exhibit increasingly sluggish behavior until it eventually stops working. Likely, you will be required to re-boot to restore normal behavior.
(I would not recommend running it)
#include <ansi_c.h>
char *buf=0;
int main(void)
{
long long i;
char text[]="a;lskdddddddd;js;'";
buf = malloc(1000000);
strcat(buf, "a;lskdddddddd;js;dlkag;lkjsda;gkl;sdfja;klagj;aglkjaf;d");
i=1;
while(strlen(buf) < i*1000000)
{
strcat(buf,text);
if(strlen(buf) > (i*10000) -10)
{
i++;
buf = realloc(buf, 10000000*i);
}
}
return 0;
}
Memory usage after just 30 seconds of running this memory pig:
I guess that has to do with scope 'ending' really often (at the end of a function) meaning if you return from that function creating a and allocating b, you will have freed in a sense the memory taken by a, and lost for the remainder of the execution memory used by b
Try calling that function a a handful of times, and you'll soon exhaust all of your memory. This never happens with stack variables (except in the case of a defectuous recursion)
Memory for local variables automatically is reclaimed when the function is left (by resetting the frame pointer).
The problem is that memory you allocate on the heap never gets freed until your program ends, unless you explicitly free it. That means every time you allocate more heap memory, you reduce available memory more and more, until eventually your program runs out (in theory).
Stack memory is different because it's laid-out and used in a predictable pattern, as determined by the compiler. It expands as needed for a given block, then contracts when the block ends.
So why is it bad practice to not free memory on the heap but okay for memory on the stack to not be freed (until the scope ends)?
Imagine the following:
while ( some_condition() )
{
int x;
char *foo = malloc( sizeof *foo * N );
// do something interesting with x and foo
}
Both x and foo are auto ("stack") variables. Logically speaking, a new instance for each is created and destroyed in each loop iteration1; no matter how many times this loop runs, the program will only allocate enough memory for a single instance of each.
However, each time through the loop, N bytes are allocated from the heap, and the address of those bytes is written to foo. Even though the variable foo ceases to exist at the end of the loop, that heap memory remains allocated, and now you can't free it because you've lost the reference to it. So each time the loop runs, another N bytes of heap memory is allocated. Over time, you run out of heap memory, which may cause your code to crash, or even cause a kernel panic depending on the platform. Even before then, you may see degraded performance in your code or other processes running on the same machine.
For long-running processes like Web servers, this is deadly. You always want to make sure you clean up after yourself. Stack-based variables are cleaned up for you, but you're responsible for cleaning up the heap after you're done.
1. In practice, this (usually) isn't the case; if you look at the generated machine code, you'll (usually) see the stack space allocated for x and foo at function entry. Usually, space for all local variables (regardless of their scope within the function) is allocated at once.
Suppose I have the following piece of code in my program:
char *ptr;
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
Will a pointer to the same memory block be assigned to ptr each time,or a separate piece of memory be reserved each time and its pointer assigned to ptr,resulting in memory leak each time malloc() is called?
I am still learning C so bear with me if it's too basic.I tried googling but found no answer.
EDIT::
Thanks for your answers.Please tell me if this approach of me deals with the memory leak risk.My program simply asks for names of 5 people and displays it,without using static arrays.After reading your answers,I put the free(ptr) inside the loop,else before I had planned to use it only once outside the loop,after the loop.Am I correct now?
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main ()
{
char *names[5],*ptr;
int i;
for(i=0;i<=4;i++)
{
ptr=malloc(sizeof(char)*10);
printf("Enter name no.%d : \n",i+1);
scanf("%s",ptr);
names[i]=malloc(strlen(ptr)+1);
strcpy(names[i],ptr);
free(ptr);
}
for(i=0;i<=4;i++)
printf("%s\n",names[i]);
}
malloc() will never return the same memory block multiple times, unless (of course) it has been free()'d since the last time it was returned. This is guaranteed by the C standard. Therefore, your code also leaks memory. Any memory allocator that handed out the same piece of memory twice would be worse than useless: Applications would step on their own toes, using the same piece of memory for different purposes, likely concurrently.
Edit: Barring buffer overflow issues, your code is correct in that it frees the 10-char buffers referenced via ptr. Calling free(ptr) just once, outside the loop, would indeed be incorrect. However, your code (as shown here) does not free the memory allocated later in the loop body stored in names[i].
A separate block of memory will be allocated each time, since C does not perform any garbage collection and no free calls are done in between the malloc calls. The first three blocks are leaked since you're not keeping pointers to them.
You can find out for yourself that the pointers are all distinct using a simple printf call:
for (int i = 0; i < 4; i++) {
ptr = malloc(10); // no need for sizeof(char), it's 1 by definition
printf("%p\n", ptr);
}
This should print four distinct numbers.
This will cause a memory leak assuming each call is successful, all but the memory allocated to the last malloc will be inaccessible. You either need to keep a pointer to each block allocated by malloc or you need to free between successive calls. so yes, malloc will attempt to allocate distinct block of memory for each call. A quick test could be as follows:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr;
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
}
This will print out the address allocated each time. If you added a free between each call to malloc you may end up with the same pointer, a quick test demonstrated this behavior.
Yes, each malloc call will allocate a new block, which means that the previous one will be leaked.
EDIT: answer to the edited part of the question
You are now correctly releasing the blocks to which ptr points, however you are not releasing those allocated for names. You would also need:
for(i=0;i<=4;i++) {
printf("%s\n",names[i]);
free(names[i]);
}
In your case, you could skip using ptr and work on names directly. Here's an equally [un]safe version:
char *names[5];
int i;
for(i=0; i < 5; i++)
{
names[i] = malloc(10);
printf("Enter name no.%d : \n",i+1);
scanf("%s",names[i]); // what if name is longer than 10 characters?
}
for(i=0; i < 5; i++)
{
printf("%s\n",names[i]);
free(names[i]);
}
However, operating system will reclaim the memory consumed by a process once the process exits, so in this simple example you don't have to worry, but I guess that this is only an illustration. I also assume that you don't care about user entering names longer than 10 characters which would write over the boundaries of allocated buffers.
Your second part is right: it's a memory leak.
A new block of memory is allocated each time you call malloc. This will create a memory leak as you have no way to reference the first three allocations to free them.
You can check memory leaks by using valgrind,its very useful in detecting memory leaks.
valgrind ./progr
This is a followup to the question I just asked here.
I've created a simple program to help myself understand memory allocation, malloc() and free(). Notice the commented out free line. I created an intentional memory leak so I can watch the Windows reported "Mem Usage" bloat slowly to 1GB. But then I found something stranger. If I comment out the loop just above the free line, so that I don't initialize my storage block with random ints, it appears that the space doesn't actually get "claimed" by the program, from the OS. Why is this?
Sure, I haven't initialized it the block, but I have claimed it, so shouldn't the OS still see that the program is using 1GB, whether or not that GB is initialized?
#include <stdio.h>
#include <stdlib.h>
void alloc_one_meg() {
int *pmeg = (int *) malloc(250000*sizeof(int));
int *p = pmeg;
int i;
// for (i=0; i<250000; i++) /* removing this loop causes memory to not be used? */
// *p++ = rand();
// free((void *)pmeg); /* removing this line causes memory leak! */
}
main()
{
int i;
for (i=0; i<1000; i++) {
alloc_one_meg();
}
}
Allocated memory can be in two states in Windows: Reserved, and Commited (see the documentation of VirtualAlloc about MEM_RESERVE: "Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.").
If you allocate memory but do not use it, it remains in the Reserved state, and the OS doesn't count that as used memory. When you try to use it (whether it is only on write, or on both read and write, I do not know, you might want to do a test to find out), it turns into Commited memory, and the OS counts it as used.
Also, the memory allocated by malloc will not be full of 0's (actually it may happen to be, but it's not guaranteed), because you have not initialised it.
it could be compiler optimization : the memory is not used at all, so a possible optimization is to not allocate this memory depening on compiler and on optimization options.
i tested your code, the line : free((void *)pmeg); does not cause any memory leak for me.
I have a doubt regarding heap in program execution layout diagram of a C program.
I know that all the dynamically allocated memory is allotted in heap which grows dynamically. But I would like to know what is the max heap size for a C program ??
I am just attaching a sample C program ... here I am trying to allocate 1GB memory to string and even doing the memset ...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *temp;
mybuffer=malloc(1024*1024*1024*1);
temp = memset(mybuffer,0,(1024*1024*1024*1));
if( (mybuffer == temp) && (mybuffer != NULL))
printf("%x - %x\n", mybuffer, &mybuffer[((1024*1024*1024*1)-1)]]);
else
printf("Wrong\n");
sleep(20);
free(mybuffer);
return 0;
}
If I run above program in 3 instances at once then malloc should fail atleast in one instance [I feel so] ... but still malloc is successfull.
If it is successful can I know how the OS takes care of 3GB of dynamically allocated memory.
Your machine is very probably overcomitting on RAM, and not using the memory until you actually write it. Try writing to each block after allocating it, thus forcing the operating system to ensure there's real RAM mapped to the address malloc() returned.
From the linux malloc page,
BUGS
By default, Linux follows an optimistic memory allocation strategy.
This means that when malloc() returns non-NULL there is no guarantee
that the memory really is available. This is a really bad bug. In
case it turns out that the system is out of memory, one or more pro‐
cesses will be killed by the infamous OOM killer. In case Linux is
employed under circumstances where it would be less desirable to sud‐
denly lose some randomly picked processes, and moreover the kernel ver‐
sion is sufficiently recent, one can switch off this overcommitting
behavior using a command like:
# echo 2 > /proc/sys/vm/overcommit_memory
See also the kernel Documentation directory, files vm/overcommit-
accounting and sysctl/vm.txt.
You're mixing up physical memory and virtual memory.
http://apollo.lsc.vsc.edu/metadmin/references/sag/x1752.html
http://en.wikipedia.org/wiki/Virtual_memory
http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory
Malloc will allocate the memory but it does not write to any of it. So if the virtual memory is available then it will succeed. It is only when you write something to it will the real memory need to be paged to the page file.
Calloc if memory serves be correctly(!) write zeros to each byte of the allocated memory before returning so will need to allocate the pages there and then.