I wrote some code in C and I need to handle the situation that fail to malloc() or realloc(). I know that if memory allocation failed, it will return NULL, and I wrote something as follow:
char *str = (char *)malloc(sizeof(char));
if (str == NULL)
{
puts("Malloc Failed.");
// do something
}
// do something else
So the problem is, how can I test this part of code?
It is impossible to run out of my memory on my machine by hand. So I want to restrict the biggest memory size it can use.
Can I specify the maximum memory size my program can use when I compile/run it? Or is there any technique to do it?
For your information, I write code in standard C, compile it with gcc, and run it on Linux environment.
Many thanks in advance.
You can create a test file that essentially overrides malloc.
First, use a macro to redefine malloc to a stub function, for example my_malloc. Then include the source file you want to test. This causes calls to malloc to be replaced with my_malloc which can return whatever you want. Then you can call the function to test.
#include <stdio.h>
#include <stdlib.h>
#define malloc(x) my_malloc(x)
#include "file_to_test.c"
#undef malloc
int m_null;
void *my_malloc(size_t n)
{
return m_null ? NULL : malloc(n);
}
int main()
{
// test null case
m_null = 1;
function_to_test();
// test non-null case
m_null = 0;
function_to_test();
return 0;
}
you can simply give malloc a big number to allocate and it will fail to allocate the size you trying to.
Related
I'm writing a simple utility in C and I'm writing codes to print error messages in STDERR.
I have a struct, defined as:
struct arguments
{
FILE *source;
int modifier_value;
int filesize;
};
I have declared a pointer to the above struct, and allocated memory to it:
struct arguments *arg = NULL;
arg = malloc(sizeof(struct arguments));
if(arg == NULL)
{
fprintf(stderr, "error: malloc - %s\n", strerror(errno)); //I know i could use perror as well, but I like the convention of using fprintf() for both stdout, stderr, and other file streams, just for symmetry
return EXIT_FAILURE;
}
As you can see, I have only allocated memory sufficient to store one object of type struct arguments and I still error checking for it.
The problem is I have many pointers like that which points to space of one object, and error checking all of them just increases number of codes and affects readability of code.
Is it a "good practice" / "is it ok" if I ignore error checking just for the reason that I'm not allocating memory too much memory (I heard something about paging and I think system combines many pages if I request for too much memory and chances of error in that case would be high, but not for memory request of something like 64 bytes).
Is it a "good practice" / "is it ok" if I ignore error checking just for the reason that I'm not allocating memory too much memory
It is poor practice to fail to error-check function calls that report on errors, except where you don't care whether the call succeeded. And you always care whether malloc() succeeds, or else you shouldn't be calling it in the first place. You don't know whether you are allocating too much memory unless you check whether your malloc() calls succeed.
The problem is I have many pointers like that which points to space of one object, and error checking all of them just increases number of codes and affects readability of code.
In the first place, use dynamic allocation only where you actually need it. Some people seem to have the idea that they need dynamic allocation wherever they want a pointer to an object. This absolutely is not the case. You need pointers if you are performing dynamic allocation, but you don't necessarily need dynamic allocation where you use pointers. Very often, static or automatic allocation can be combined with the address-of operator (unary &) instead. For example:
{
struct arguments arg = {0};
init_arguments(&arg);
do_something(&arg);
// all done with arg
}
You need dynamic allocation only when (i) you do not know at compile time how much memory you will need, or (ii) you need an object whose lifetime extends past the termination of the innermost block enclosing its creation.
When you really do need dynamic allocation, you can reduce the amount of boilerplate code by using a macro or a wrapper function. Similar applies to performing other success checks. For example, use a function such as this instead of using malloc() directly:
void *checked_malloc(size_t size) {
void *result = malloc(size);
if (result == NULL && size != 0) {
fputs("error: malloc failed -- aborting...\n", stderr);
abort();
}
return result;
}
Create allocation wrapper functions to make always checking allocation success easy.
To expand on #Weather Vane idea of passing an argument to identify the caller, yet do it in a macro wrapper.
my_malloc.h
#ifndef MY_MALLOC
#define MY_MALLOC(size) my_malloc((size), __FUNC__, __LINE__)
#include <stdlib.h>
// Return a valid allocation or don't return.
void *my_malloc(size_t size, const char *func, unsigned line);
#endif
my_malloc.c
#include "my_maloc.h"
#include <stdio.h>
#include <stdlib.h>
void *my_malloc(size_t size, const char *func, unsigned line) {
if (size == 0) {
return NULL;
}
void *ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Failed to allocate %zu bytes at \"%s()\", line %u\n",
size, func, line);
exit(EXIT_FAILURE);
}
return ptr;
}
user_code.c
#include "my_malloc.h"
...
// No need to explicitly pass the function name, line number
arg = MY_MALLOC(sizeof *arg * n);
// Error checking not needed.
...
free(arg);
I'd even consider a matching MY_FREE where freeing passes in the pointer and the expected size. Then those 2 routines could keep allocation statistics, free size validation, ...
If you have many objects, you cam allocate memory for all immediately:
void *pvc;
pvc = malloc(how_many_for_all);
and then consecutively declare pointers to objects like this:
Obj1 *p1;
Obj2 *p2;
Obj3 *p3;
p1 = (Obj1)pvc;
p2 = (Obj2)(pvc + sizeof(Obj1));
p3 = (Obj3)(pvc + sizeof(Obj1) + sizeof(Obj2));
This is pseudocode sooner. Compiler will be make warnings, but this works.
I have issues with my program.
When I launch the program, the console doesn't show the 2 numbers that it should , instead it only shows this:
Process returned -1073741819 (0xC0000005) execution time : 1.759 s
This is my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
Test(int* Ptr)
{
Ptr=(int*)malloc(8);
if(Ptr==0)
{
printf("malloc error\n");
}
Ptr[0]=155;
Ptr[1]=800;
}
int main()
{
int* m_Ptr=0;
Test(m_Ptr);
printf("%d %d",m_Ptr[0],m_Ptr[1];
return 0;
}
You're main issue is that the pointer you pass into test() is passed by copy. So m_ptr is null when its passed in and its still null when test returns.
You probably want to change your function slightly to something more like:
int* Test()
{
int * Ptr = (int*) malloc(20);
if(Ptr==0)
{
printf("malloc error\n");
}
Ptr[0]=155;
Ptr[1]=800;
return Ptr; // Return the pointer by value
}
And use like (in main):
int* m_Ptr = Test(m_Ptr);
// Now m_Ptr actually points to something...
The argument Ptr in test is a different object in memory from m_Ptr in main - any changes to test::Ptr (such as assigning it the result of malloc) are not reflected in main::m_Ptr. You will either have to pass a pointer or a reference to m_Ptr to test, or test will have to return a pointer value that you assign to m_Ptr:
m_Ptr = Test(); // returns pointer to newly allocated memory.
If this is meant to be C++, then don't use malloc (or calloc, or realloc). Either use a standard container like a vector or set (which automatically grow as new items are added), or use the new operator to manually allocate memory to some kind of smart pointer. Don't use C-style memory management in C++ code; it's labor-intensive, it's unsafe, and it's easy to get things wrong.
With malloc(8) you request 8 bytes.
On a 64bit system sizeof(int) could be 8 bytes.
If so, the line Ptr[1]=800; actually writes to memory beyond the allocated Arena.
Try to change the malloc line to
Ptr=(int*)malloc(sizeof(int)*2)
I'm currently trying to find out the best way to program functionally in C, but I'm having a problem in freeing the memory after being allocated.
consider the following example: (I deleted the unimportant parts because I thought it would be too long)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* someFunction(int someParam)
{
//... some code ...
char* str = malloc((strlen)*sizeof(char));
//... some code ...
return(str);
}
int main()
{
//... some code ...
printf("%s\n", someFunction(someParam))
return 0;
}
Here, since someFunction is called inside printf, and there seems to be no way to free the memory that's been allocated for the string. Note that this code DOES compile with GCC, but I'm looking for a way to reduce the memory load overall.
I could define a temporary variable and free it later in the main function, but the code would be more difficult to read as the functions get nested more.
You need to use a temporary variable so you can free it later. Otherwise you'll have a memory leak each time you call the function like this.
C doesn't have any form of automatic memory management, except that most operating systems will reclaim all of the process's private memory when it terminates. Unfortunately, this means that your program will need to be a little more verbose.
If you really want to have that functional style, you can pass an additional (pointer) argument where you record whatever needs to be cleaned up:
char* someFunction(int someParam, void **cleanup)
{
//... some code ...
char* str = malloc((strlen)*sizeof(char));
//... some code ...
*cleanup = str;
return(str);
}
int main()
{
void *cleanup = 0;
//... some code ...
printf("%s\n", someFunction(someParam, &cleanup));
free(cleanup);
return 0;
}
If you want to extend this, you can replace the simple void * with a data structure that can record multiple pointers that need later cleanup, and add multiple allocated things to it, and then clean them up all at once at the end.
Simply allocate the buffer in main and pass it as a parameter to the function so that it may populate it.
This way you don't have to have global variables.
//... some code ...
int someFunction(int someParam, char *output, int somesize)
{
//... some code ...
// update a maximum of 'somesize' of output
snprintf(output, somesize, "some special string");
//... some code ...
return strlen("some special string");
}
int main()
{
char buffer[somesize]; // or use malloc and free at the end
//... some code ...
if (someFunction(someParam, buffer, somesize) > 0) {
printf("%s\n", buffer);
}
return 0;
}
we wrote a program that reads comma-separated integer-values into an array and tries processing them with a parallel structure.
By doing so, we found out that there is a fixed limitation for the maximum size of the dynamic array, which usually gets allocated dynamically by doubling the size. Yet for a dataset with more than 5000 values, we can't double it anymore.
I am a bit confused right now, since technically, we did everything the way other posts pointed out we should do (use realloc, don't use stack but heap instead).
Note that it works fine for any file with less or equal than 5000 values.
We also tried working with realloc, but to the same result.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// compile with gcc filename -lpthread -lm -Wall -Wextra -o test
int reader(int ** array, char * name) {
FILE *fp;
int data,row,col,count,inc;
int capacity=10;
char ch;
fp=fopen(name,"r");
row=col=count=0;
while(EOF!=(inc=fscanf(fp,"%d%c", &data, &ch)) && inc == 2){
if(capacity==count)
// this is the alternative with realloc we tried. Still the same issue.
//*array=malloc(sizeof(int)*(capacity*=2));
*array = realloc(*array, sizeof(int)*(capacity*=2));
(*array)[count++] = data;
//printf("%d ", data);
if(ch == '\n'){
break;
} else if(ch != ','){
fprintf(stderr, "format error of different separator(%c) of Row at %d \n", ch, row);
break;
}
}
// close file stream
fclose(fp);
//*array=malloc( sizeof(int)*count);
*array = realloc(*array, sizeof(int)*count);
return count;
}
int main(){
int cores = 8;
pthread_t p[cores];
int *array;
int i = 0;
array=malloc(sizeof(int)*10);
// read the file
int length = reader(&array, "data_2.txt");
// clean up and exit
free(array);
return 0;
}
EDIT: I included the realloc-command we tried and changed the values back to our original testing values (starting at 10). This didn't impact the result though, or rather still does not work. Thanks anyways for pointing out the errors! I also reduced the included code to the relevant part.
I can't really get my head around the fact that it should work this way, but doesn't, so it might just be a minor mistake we overlooked.
Thanks in advance.
New answer after question has been updated
The use of realloc is wrong. Always do realloc into a new pointer and check for NULL before overwriting the old pointer.
Like:
int* tmp = realloc(....);
if (!tmp)
{
// No more memory
// do error handling
....
}
*array = tmp;
Original answer (not fully valid after question has been updated)
You have some serious problems with the current code.
In main you have:
array=malloc(sizeof(int)*10); // This only allocates memory for 10 int
int length = reader(&array, "data_1.txt");
and in reader you have:
int capacity=5001;
So you assume that the array capacity is 5001 even though you only reserved memory for 10 to start with. So you end up writing outside the reserved array (i.e. undefined behavior).
A better approach could be to handle all allocation in the function (i.e. don't do any allocation in main). If you do that you shall initialize capacity to 0 and rewrite the way capacity grows.
Further, in reader you have:
if(capacity==count)
*array=malloc(sizeof(int)*(capacity*=2));
It is wrong to use malloc as you loose all data already in the array and leak memory as well. Use realloc instead.
Finally, you have:
*array=malloc( sizeof(int)*count);
Again this is wrong for the same reason as above. If you want to resize to the exact size (aka count) use realloc
I have a structure defined like so:
typedef struct {
int n;
int *n_p;
void **list_pp;
size_t rec_size;
int n_buffs;
size_t buff_size
} fl_hdr_type;
and in my code I Have a function for initlialization that has the following
fl_hdr_type *fl_hdr;
fl_hdr = malloc(sizeof(fl_hdr_type) + (buff_size_n * rec_size_n));
where those buffer size are passed in to the function to allow space for the buffers as well.
The size is pretty small typically..100*50 or something like that..plenty of memory on this system to allocate it.
I can't actually post the stack trace because this code is on another network, but some information pulled from dbx on the core file:
buff_size_n = 32, rec_size_n = 186
and the stack..line numbers from malloc.c
t_splay:861
t_delete:796
realfree: 531
cleanfree:945
_malloc:230
_malloc:186
Any ideas why this fails?
Try running your program through valgrind, see what it reports. It's possible in some other part of the program you have corrupted free lists or something else malloc looks at.
What you need to do is simply do this.
fl_hdr = malloc(sizeof(fl_hdr_type));
The list_pp is a dynamic array of void* and you need to allocate that to the size you need with another malloc.
list_pp is simply a pointer to something else that is allocated on then heap.
If you want to allocate in place with one malloc, then you will need to define it as an array of the actual types you want. The compiler needs to know the types to be able to perform the allocation.
If what you are looking for is dynamic arrays in C, then look at this.
You need to explicitly assign n_p and list_pp to the appropriate offsets.
fl_hdr_type *fl_hdr;
fl_hdr = malloc(sizeof(fl_hdr_type) + (buff_size_n * rec_size_n));
fl_hdr->n_p = fl_hdr+sizeof(fl_hdr_type);
fl_hdr->list_pp = fl_hdr->n_p + (num_n * sizeof(int));
If you're going to do this, I'd recommend putting the pointers at the end of the struct, instead of the middle. I'm with Romain, though, and recommend you use separate calls to malloc() instead of grabbing everything with one call.
I made your example into a program, and have absolutely no issues running it. If you can compile and run this simple code (and it works), you have corrupted the heap somewhere else in your program. Please run it through Valgrind (edit as User275455 suggested, I did not notice the reply) and update your question with the output that it gives you.
Edit
Additionally, please update your question to indicate exactly what you are doing with **list_pp and *n_p after allocating the structure. If you don't have access to valgrind, at least paste the entire trace that glibc printed when the program crashed.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int n;
int *n_p;
void **list_pp;
size_t rec_size;
int n_buffs;
size_t buff_size;
} fl_hdr_type;
static size_t buff_size_n = 50;
static size_t rec_size_n = 100;
static fl_hdr_type *my_init(void)
{
fl_hdr_type *fl_hdr = NULL;
fl_hdr = malloc(sizeof(fl_hdr_type) + (buff_size_n * rec_size_n));
return fl_hdr;
}
int main(void)
{
fl_hdr_type *t = NULL;
t = my_init();
printf("Malloc %s\n", t == NULL ? "Failed" : "Worked");
if (t != NULL)
free(t);
return 0;
}