How to create a function that uses up all malloced memory - c

I want to make a function that I can stick before the stuff in a test main and it will use up all the space for malloc (causing future allocations to fail). The problem is that once the function finishes everything seems to get freed...
#include <stdlib.h>
void breakmalloc(void)
{
int *i;
int n;
n = 1;
i = &n;
while (n)
{
while (i)
{
i = malloc(n);
if (i)
n = n + n;
}
n = n / 2;
i = &n;
}
}
it exits the function when I test it so it would seem that all of the space has been used up but as soon as the function finishes I can then malloc other stuff in future functions.

I don't know if the test result using your trick handled green/red correctly since memory is exhausted. If your code call malloc to allocate memory, and you want test it. I guess you've better to use simple trick.
#ifdef TEST
# undef malloc
# define malloc(x) (NULL)
#endif

Some operating systems such an Linux perform optimistic memory allocation. That means that whatever memory is returned by malloc and family is not immediately allocated and therefore not necessarily available. So even if you were to allocate 100GB of memory malloc would still probably return non-NULL.
The memory won't actually get allocated until you use it. So to force it, you should memset the block.
i = malloc(n);
if (i) {
memset(i, 0, n);
n = n + n;
}

#include <stdlib.h>
#include <stdio.h>
void breakmalloc(void)
{
char *buff = NULL;
int size = 1024;
while (1) {
buff = (char *)malloc(size);
if (buff) {
memset(buff, 1, size); //must use it, or optimized by system
} else {
printf("memory insufficient!");
break;
}
}
}
try like this

Related

Issue writing in a pointer allocated through a function

I need to write in a variable allocated through a function. I found a lot of threads discussing this, such as Allocating a pointer by passing it through two functions and How to use realloc in a function in C, which helped me fixing some issues, but one remains and I can't find the cause.
Consider the following code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void foo(uint64_t** m)
{
*m = realloc(*m, sizeof(uint64_t) * 4);
*m[0] = (uint64_t)1;
//*m[1] = (uint64_t)2; // create a segfault and crash right here, not at the print later
}
int main()
{
uint64_t* memory = NULL;
foo(&memory);
for(int i = 0; i < 4; i++)
printf("%d = %ld\n", i, memory[i]);
return 0;
}
I send the address of memory to foo, which takes a double pointer as an argument so it can modify the variable. The realloc function need a size in bytes, so I make sure to ask for 4 * sizeof(uint64_t) to have enough space to write 4 64-bits int. (The realloc is needed, I don't need malloc).
I can then write in m[0] without issue. But if I write in m[1], the program crashes.
What did I do wrong here ?

C - Self-referencing structure and realloc

I've got a problem with calling realloc on self-referencing structure. When I run this program, I get error *** Error in ...: realloc(): invalid next size: 0x0000000000602160 ***. I suppose the problem is related to the last line, because program runs without any problem if I comment it.
This is the smallest (not) working piece of code:
#include <string.h>
#include <stdlib.h>
typedef struct structure {
int connections;
struct structure *links;
} structure;
int main(int argc, char *argv[]) {
int struct_count;
int i, from, to, offset;
structure *structs;
struct_count = 2;
structs = malloc(sizeof(structure) * struct_count);
memset(structs, 0, sizeof(structure) * struct_count);
for(i = 0; i < struct_count; i++) {
structs[i].links = malloc(1);
structs[i].connections = 0;
}
for(i = 0; i < 100; i++) {
from = 0;
to = 1;
offset = structs[from].connections++;
structs[from].links = realloc(structs[from].links, sizeof(int) * (offset + 1));
structs[from].links[offset] = structs[to]; // This is the problematic line - why?
}
}
And my question: what's wrong in that code?
The problem is the first time you allocate it, it's not enough. To allocate n elements of a given type you can use
structs[i].links = malloc(n * sizeof(*structs[i].links));
and the same goes wit realloc() you also need to make sure that realloc() doesn't return NULL, suppose that after allocating space for n structures with the line above you want to resize to store n + 1 instances, then
struct structure *links;
links = realloc(structs[i].links, (n + 1) * sizeof(*links));
if (links == NULL)
{
/* Depending on the way your program is designed */
probably_free_links(&structs[i].links);
/* ^ make it `NULL' inside */
allocation_failure_do_something_about_it_but_do_not_continue();
}
structs[i].links = links;
you can make structs[i].links = NULL; initially and realloc() will behave as malloc() the first time.
Write your programs as if all errors are possible, and do something about them don't just let your program invoke undefined behavior and make it a mistery to you and your program users.
If You will increase the Blueprint of structure and decrease the size of loop it will run perfectly..
**For Example:-**without manipulating run your program just decrease the loop condition from 100 to 2. It will run perfectly.
If you want to increase loop size you have to increase the size of structure.

Freeing all allocated memory in case of failure

I'm working on a C project (assignment for school). One of the demands is that in case of malloc() failure, the program must free() all allocated memory and exit().
Consider a case where function A() constructs a linked-list and in each iteration it calls to another function, B(). Now, if a malloc failure occured at B(), it must free() the memory it allocated but function A() should do that as well.
Things are getting quite complicated when you have a tree of function calls larger than two.
In my previous project I used a flag to notify a malloc() failure - if a function uses another function which may use malloc(), it has to check the flag right after. It worked, but code got kinda messy.
Is there a neat solution for this problem?
Of course, with "real" applications all memory is de-allocated by the OS, but I guess this demand is pedagogical..
I think the easiest approach is to create a custom allocator (as somebody already noted in a deleted post) to keep track of all your allocations, then do a custom deallocator, use these for all your heap memory needs.
if a malloc fails you have the list of previously allocated blocks at easy reach.
e.g.
(you need to redo this cause it is not effective and should be optimized but shows the principle and only ocular compilation)
typedef struct
{
void* pMemory; /* for the allocated memory */
size_t size; /* for better debugging */
} MemoryBlock;
#define MAXBLOCKS 1000
MemoryBlock myheap[MAXBLOCKS]; // global so zero:ed
static int block = 0;
void* myalloc(size_t size)
{
static int block = 0;
// you should check vs MAXBLOCKS
myheap[block].pMemory = malloc(size);
myheap[block].size = size;
// check if it failed.
if ( myheap[block].pMemory == NULL )
{
for (int i = 0; i < block; ++i)
{
myfree(myheap[i].pMemory);
}
fprintf( stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
else
{
return myheap[block++].pMemory;
}
}
void myfree(void* p)
{
for (int i = 0; i < block; ++i)
{
if ( p == myheap[i].pMemory )
{
free(myheap[i].pMemory);
myheap[i].pMemory = NULL;
return;
}
}
}
Yes. The best (and conventional) way is to initialize every pointer value to zero. Then set it during the malloc() assignment. Ex: myPtr = malloc( 10 );
It will be zero in case of failure, and you check that. And finally, when you go about freeing, you always check the pointer value before calling free():
if ( myPtr != 0 )
free( myPtr );
There is no need for an extra flag.
Are you having issue checking for errors or handling them? If you want info on catching them, use donjuedo's suggestion.
For ideas on freeing memory in the event of error, try one of these two methods:
1) For a uni-directional linked-list, keep a special pointer that points to the head of the list. In your cascading free function, start at the head, capture the next-pointer in a temp variable, free the head, move to the next structure in the list using the temp-pointer, and repeat the process until the next-pointer == 0.
2) For a bi-directional linked-list (my preference) you don't need to keep a special pointer to the head of the list. Assuming you are still at the tail, just capture the previous-pointer into a temp variable, free the tail, move back using the temp-pointer, and repeat the process until the previous-pointer == 0
You could look into the atexit() function, to register code that will be executed when the program terminates. Such code can then check if there is anything that needs to be free()d.
Note that atexit() has no way to unregister. So you need to make sure that you register each cleanup function only once, and that it does the right thing when there is nothing to clean up.
#include <stdlib.h>
#include <stdio.h>
int *ptr1;
char *ptr2;
int clean1_registered, clean2_registered;
void clean1(void)
{
printf("clean1 called\n");
if (ptr1) {
free(ptr1);
ptr1 = NULL;
}
}
void clean2(void)
{
printf("clean2 called\n");
if (ptr2) {
free(ptr2);
ptr2 = NULL;
}
}
void B(void)
{
ptr2 = malloc(100);
if (!clean2_registered) {
atexit(clean2);
}
}
void A(void)
{
ptr1 = malloc(100 * sizeof(int));
if (!clean1_registered) {
atexit(clean1);
}
B();
}
int main(int argc, char **argv)
{
A();
}

Is it OK to malloc an array in a called function but free it in the calling function?

I'm not an expert in C, but here's what I'm trying to do:
int main(void) {
double *myArray;
...
myFunction(myArray);
...
/* save myArray contents to file */
...
free(myArray);
...
return 0;
}
int myFunction(double *myArray) {
int len=0;
...
/* compute len */
...
myArray = malloc( sizeof(double) * len );
if (myArray == NULL)
exit(1);
...
/* populate myArray */
...
return 0;
}
I'd like to save the contents of myArray inside main, but I don't know the size required until the program is inside myFunction.
Since I'm using CentOS 6.2 Linux, which I could only find a gcc build available up to 4.4.6 (which doesn't support C99 feature of declaring a variable-length array; see "broken" under "Variable-length arrays in http://gcc.gnu.org/gcc-4.4/c99status.html), I'm stuck using -std=c89 to compile.
Simple answer is no.
You are not passing back the pointer.
use
int main(void) {
double *myArray;
...
myFunction(&myArray);
...
/* save myArray contents to file */
...
free(myArray);
...
return 0;
}
int myFunction(double **myArray) {
int len=0;
...
/* compute len */
...
*myArray = malloc( sizeof(double) * len );
if (NULL == *myArray)
exit(1);
...
EDIT
poputateThis = *myArray;
/* populate poputateThis */
END OF EDIT
...
return 0;
EDIT
Should simplify thigs for your
}
What you are doing is not OK since myFunction doesn't change the value myArray holds in main; it merely changes its own copy.
Other than that, it's OK even if stylistically debatable.
As a question of good design and practice (apart from syntax issues pointed out in other answers) this is okay as long as it is consistent with your code base's best practices and transparent. Your function should be documented so that the caller knows it has to free and furthermore knows not to allocate its own memory. Furthermore consider making an abstract data type such as:
// myarray.h
struct myarray_t;
int myarray_init(myarray_t* array); //int for return code
int myarray_cleanup(myarray_t* array); // will clean up
myarray_t will hold a dynamic pointer that will be encapsulated from the calling function, although in the init and cleanup functions it will respectively allocate and deallocate.
What you want to do is fine, but your code doesn't do it -- main never gets to see the allocated memory. The parameter myArray of myFunction is initialized with the value passed in the function call, but modifying it thereafter doesn't modify the otherwise-unrelated variable of the same name in main.
It appears in your code snippet that myFunction always returns 0. If so then the most obvious way to fix your code is to return myArray instead (and take no parameter). Then the call in main would look like myArray = myFunction();.
If myFunction in fact already uses its return value then you can pass in a pointer to double*, and write the address to the referand of that pointer. This is what Ed Heal's answer does. The double ** parameter is often called an "out-param", since it's a pointer to a location that the function uses to store its output. In this case, the output is the address of the buffer.
An alternative would be to do something like this:
size_t myFunction(double *myArray, size_t buf_len) {
int len=0;
...
/* compute len */
...
if (buf_len < len) {
return len;
}
/* populate myArray */
...
return len;
}
Then the callers have the freedom to allocate memory any way they like. Typical calling code might look like this:
size_t len = myFunction(NULL, 0);
// warning -- watch the case where len == 0, if that is possible
double *myArray = malloc(len * sizeof(*myArray));
if (!myArray) exit(1);
myFunction(myArray, len);
...
free(myArray);
What you've gained is that the caller can allocate the memory from anywhere that's convenient. What you've lost is that the caller has to write more code.
For an example of how to use that freedom, a caller could write:
#define SMALLSIZE 10;
void one_of_several_jobs() {
// doesn't usually require much space, occasionally does
double smallbuf[SMALLSIZE];
double *buf = 0;
size_t len = myFunction(smallbuf, SMALLSIZE);
if (len > SMALLSIZE) {
double *buf = malloc(len * sizeof(*buf));
if (!buf) {
puts("this job is too big, skipping it and moving to the next one");
return;
}
} else {
buf = smallbuf;
}
// use buf and len for something
...
if (buf != smallbuf) free(buf);
}
It's usually an unnecessary optimization to avoid a malloc in the common case where only a small buffer is needed -- this is only one example of why the caller might want a say in how the memory is allocated. A more pressing reason might be that your function is compiled into a different dll from the caller's function, perhaps using a different compiler, and the two don't use compatible implementations of malloc/free.

Memory Allocation Tracking in C -- Am I doing this right?

Just for fun (and for C programming practice) I wrote the following piece of code that does the following:
Acts as a tracking system for memory allocations
Frees all dynamically allocated memory with a function call
Here is the code:
typedef enum _OpMode {
OM_APPEND,
OM_DESTROY
} OP_MODE;
void refOp(void *ptr, OP_MODE mode) {
/* contains static array of pointers and provides an interface to that
array */
static void **references = NULL;
static int size = 0;
static int reset = 0;
if (reset) {
reset = 0;
references = NULL;
size = 0;
}
switch (mode) {
case OM_APPEND:
//add a pointer to reference array
references = (void**) realloc(references, sizeof(void*) * (size + 1));
references[size++] = ptr;
break;
case OM_DESTROY:
//free memory at all pointers kept in reference array
for (int i = 0; i < size; i++) {
free(references[i]);
references[i] = NULL;
}
free(references);
reset = 1;
break;
default:
printf("Invalid enum value '%d' passed as mode.\n", mode);
break;
}
}
void refDestroyAll() {
//Wrapper function
refOp(NULL, OM_DESTROY);
}
void *myAlloc(void* ptr, size_t size) {
/* Allocates memory and stores pointer copy in reference array */
void *tmp_ptr;
tmp_ptr = realloc(ptr, size);
refOp(tmp_ptr, OM_APPEND);
return tmp_ptr;
}
The idea is that one would use myAlloc() instead of malloc or realloc to dynamically allocate memory. And one would use refDestroyAll() to free all memory that was created with myAlloc().
I've done some testing, and it seems to be working, but I can't help feeling that I'm missing something important. Does this code actually work as intended, or am I leaking memory when I call refDestroyAll()?
You have a bug, that could cause a segmentation fault. realloc() could return the same pointer as it is given, in which case you would have added it twice to the array. When you call your free function, it would try and free the same pointer twice, resulting in a segmentation fault error.
Additionally, I don't understand why you have the reset parameter. Why not simply set references and size to 0 in the OM_DESTROY case? It is good practice to always set a pointer to NULL immediately after freeing it.

Resources