using my own malloc()

A

arnuld

At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ?


#include <stdio.h>
#include <stdlib.h>


enum { ARRSIZE = 10 };

struct my_struct
{
int i;
char arrc[ARRSIZE];
};


void* malloc_my_struct(int num, size_t s);
void free_my_struct( struct my_struct** p );


int main(void)
{
struct my_struct* m = malloc_my_struct(1, sizeof(*m));

printf("Memory allocated: %p\n", (void*)m);
free_my_struct(&m);
printf("Memory freed: %p\n", (void*)m);
return 0;
}


void* malloc_my_struct(int num, size_t s)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);

return p;
}


void free_my_struct( struct my_struct** p )
{
free(*p);
*p = NULL;
}


============ OUTPUT ======================
[arnuld@dune programs]$ gcc -std=c99 -pedantic -Wall -Wextra xmalloc.c
[arnuld@dune programs]$ ./a.out
Memory allocated: 0x804a008
Memory freed: (nil)
[arnuld@dune programs]$



I got this idea actually from GNU C Library manual:
http://www.gnu.org/software/hello/manual/libc/Malloc-Examples.html#Malloc-Examples
.. 2md, I am using -std=c99 rather than -ansi flag because I am unable
to find any alternative to __func__ . Do you know any ?
 
F

Falcon Kirtaran

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ?


#include <stdio.h>
#include <stdlib.h>


enum { ARRSIZE = 10 };

struct my_struct
{
int i;
char arrc[ARRSIZE];
};


void* malloc_my_struct(int num, size_t s);
void free_my_struct( struct my_struct** p );


int main(void)
{
struct my_struct* m = malloc_my_struct(1, sizeof(*m));

printf("Memory allocated: %p\n", (void*)m);
free_my_struct(&m);
printf("Memory freed: %p\n", (void*)m);
return 0;
}


void* malloc_my_struct(int num, size_t s)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);

return p;
}


void free_my_struct( struct my_struct** p )
{
free(*p);
*p = NULL;
}


============ OUTPUT ======================
[arnuld@dune programs]$ gcc -std=c99 -pedantic -Wall -Wextra xmalloc.c
[arnuld@dune programs]$ ./a.out
Memory allocated: 0x804a008
Memory freed: (nil)
[arnuld@dune programs]$



I got this idea actually from GNU C Library manual:
http://www.gnu.org/software/hello/manual/libc/Malloc-Examples.html#Malloc-Examples
. 2md, I am using -std=c99 rather than -ansi flag because I am unable
to find any alternative to __func__ . Do you know any ?

There is no reason why this idea is intrinsically bad.

- --
- --Falcon Darkstar Christopher Momot
- --
- --OpenPGP: (7902:4457) 9282:A431

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkpxMhsACgkQeQJEV5KCpDF0DgCgmvuHxgyxIC8NCJ5bbMs/zkfj
vNYAnitU76qg18HFKQXFemRp6xOnMu9+
=ZfZ9
-----END PGP SIGNATURE-----
 
J

James Kuyper

arnuld said:
At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ?

You're not writing your own malloc() - what you're doing is called
writing a wrapper for malloc().

....
void* malloc_my_struct(int num, size_t s)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);

return p;
}

The one problem I see with this approach is that it makes the decision
about whether and how to report a problem, at the very lowest level of
the program. You might want to re-use your code in a new program, but
that new program might have different restrictions on how problems
should be reported. You can increase the re-usability of your code by
deferring such decisions, as far as possible, to the calling routine.

For instance, most of my programs are written to run under a production
system where they are prohibited from reading or writing directly to or
from stdin, stderr or stdout, or indeed to any stream opened by any
method other than by calling certain routines provided in a library as
part of the production system. There's a standard message log that my
programs are supposed to write all error messages to, by calling other
routines in that same library.

Other people write code for GUI applications where messages written to
stderr will never be seen; in order to be useful, error messages have to
be displayed in a message box, or by some other GUI-specific method.
 
A

arnuld

The one problem I see with this approach is that it makes the decision
about whether and how to report a problem, at the very lowest level of
the program. You might want to re-use your code in a new program, but
that new program might have different restrictions on how problems
should be reported. You can increase the re-usability of your code by
deferring such decisions, as far as possible, to the calling routine.


I see your point, you want to say that like fprint() gives the
flexibility of directing the output to somewhere (stdin, out and err
or file), same way my function should do it) and I need to pass that
stdin/file/stdout when I will call that function.

Anyway, I will try adding that feature. In the meantime, I changed it
a little bit:


/* Wrapper function for malloc() --- VERSION 0.1 */
#include <stdio.h>
#include <stdlib.h>


enum { ARRSIZE = 10 };

struct my_struct
{
int i;
char arrc[ARRSIZE];
};


void* malloc_my_struct(int num, size_t s, const char* f);
void free_my_struct( struct my_struct** p );


int main(void)
{
struct my_struct* m = malloc_my_struct(1, sizeof(*m), __func__);

printf("Memory allocated: %p\n", (void*)m);
free_my_struct(&m);
printf("Memory freed: %p\n", (void*)m);
return 0;
}


void* malloc_my_struct(int num, size_t s, const char* f)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", f);

return p;
}


void free_my_struct( struct my_struct** p )
{
free(*p);
*p = NULL;
}


================== OUTPUT ============================
[arnuld@dune programs]$ ./a.out
Memory allocated: 0x804a008
Memory freed: (nil)
[arnuld@dune programs]$
 
N

Nick Keighley

At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ?

 #include <stdio.h>
#include <stdlib.h>

enum { ARRSIZE = 10 };

struct my_struct
{
  int i;
  char arrc[ARRSIZE];

};

void* malloc_my_struct(int num, size_t s);
void free_my_struct( struct my_struct** p );

int main(void)
{
  struct my_struct* m = malloc_my_struct(1, sizeof(*m));

  printf("Memory allocated: %p\n", (void*)m);
  free_my_struct(&m);
  printf("Memory freed:     %p\n", (void*)m);
  return 0;

}

void* malloc_my_struct(int num, size_t s)
{
  void* p = malloc(num * s);

  if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);

and then what happens? Does the caller check for NULL?
If not...

  return p;

}

[...] I am using -std=c99 rather than -ansi flag because I am unable
to find any alternative to __func__ . Do you know any ?

__func__ is a C99 feature. C89 had no equivalent. C89 had __FILE__
and __LINE__ which might be good enough.
 
M

Morris Keesan

At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ? ....
void* malloc_my_struct(int num, size_t s)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);

return p;
}

The basic concept, of using your own function which calls malloc and
checks the result, is a sound one, and I've seen it used many times.
But if malloc returns NULL, then displaying a message on stderr and
tcontinuing your program as if the returned value were non-NULL
is a recipe for disaster. The usual reaction to malloc failure is
exit(EXIT_FAILURE), after printing the message, and after doing any
other necessary cleanup operations (i.e. cleanup operations not
accomplished by atexit()).
 
B

Barry Schwarz

I see your point, you want to say that like fprint() gives the
flexibility of directing the output to somewhere (stdin, out and err
or file), same way my function should do it) and I need to pass that
stdin/file/stdout when I will call that function.

What I think he is saying is that your allocation function should not
presume to know what the caller wants to do with the error. In some
case, even calling fprintf could be undesirable. (Consider the
possibility that the caller may free some previous allocated space and
try the allocation again.) Since you return the NULL value, the
caller must check whether it was successful or not before it attempts
to use the allocated area. Once the check fails, then the caller can
decide what to do.
 
A

arnuld

What I think he is saying is that your allocation function should not
presume to know what the caller wants to do with the error.  In some
case, even calling fprintf could be undesirable.  (Consider the
possibility that the caller may free some previous allocated space and
try the allocation again.)  Since you return the NULL value, the
caller must check whether it was successful or not before it attempts
to use the allocated area.  Once the check fails, then the caller can
decide what to do.


The malloc() returned NULL, then what I am supposed to do, check again
for NULL return value from my_malloc() ? If I need to check the
return value then why would I create my_malloc(), I will just call
malloc() directly there and check it. I just wanted to reduce the
number of lines being used in function.
 
C

Chris M. Thomasson

arnuld said:
At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ? [...]
void* malloc_my_struct(int num, size_t s)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


How do you know for sure that you cannot allocate more memory? Perhaps your
program has some caches that can be flushed, or some state than can be
reduced. malloc returning NULL does not necessarily have to result in the
termination of your program. For instance, should the whole server should do
down because malloc returns NULL? I think not... Therefore, malloc returning
NULL is NOT necessarily a _fatal_ error, well, IMVHO at least...

;^)

return p;
}
[...]
 
C

Chris M. Thomasson

Chris M. Thomasson said:
arnuld said:
At my job, I am working on a piece of code (around 16 source files)
where I have to call malloc() and free() around 20 times. Every time I
have to check the return value of malloc(). So I cam up with this idea
of writing my own malloc() and then using it. is this a good idea ? [...]
void* malloc_my_struct(int num, size_t s)
{
void* p = malloc(num * s);

if(NULL == p) fprintf(stderr, "IN: %s: Memory Exhausted, can not
allocate more memory\n", __func__);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


How do you know for sure that you cannot allocate more memory? Perhaps
your program has some caches that can be flushed, or some state than can
be reduced. malloc returning NULL does not necessarily have to result in
the termination of your program.

For instance, should the whole server should do down because malloc
returns NULL?

Yikes! That sentence should read as:



For instance, should the whole server shut down because malloc returns NULL?



Sorry for any confusion.



I think not... Therefore, malloc returning NULL is NOT necessarily a
_fatal_ error, well, IMVHO at least...

;^)

Think about create robust programs that can at least attempt to gracefully
handle errors...
 
N

Nick Keighley

The important question here is one of program design philosophy: what
is an appropriate way to handle memory failure?

In some circumstances, you may feel it appropriate to close the
application, in which case your wrapper might include an abort()
call, perhaps preceded by a call to a cleanup function. But very
often it is possible to circumvent such a drastic step, by finding
other ways to deal with the memory drought. For example, you might be
able to:

(1) break down the memory requirement into two (or more) requests;
(2) find a way to use less memory;
(3) use a fixed-length buffer;
(4) allocate an emergency reserve at the beginning of the program;
(5) find some swap space on the disk (of limited utility nowadays,
since this is basically what the system is already doing, via virtual
memory - but of course the system is likely to self-impose a limit on
how much disk space it can use, and you may feel able to use space
that your system won't let itself use);
(6) root around for swap space on some other machine connected to the
same network (if there *is* a network, of course, and if your program
has permission to do this).

do you write software that does *any* of these? The last time I did
anything like this was on an old Mac where you could flush stuff
to disc and have another go.
The most important criterion is probably that of not losing important
data.

now that seems plausible. A clean shutdown is about the best you can
mange when the memory has all gone
 
N

Nick Keighley

How do you know for sure that you cannot allocate more memory? Perhaps your
program has some caches that can be flushed, or some state than can be
reduced. malloc returning NULL does not necessarily have to result in the
termination of your program. For instance, should the whole server [go?]
down because malloc returns NULL? I think not... Therefore, malloc returning
NULL is NOT necessarily a _fatal_ error, well, IMVHO at least...

again, I know these things *could* be done but does anyone actually do
so?

[actually, it's a pretty safe bet that *someone* on clc does, I'm just
curious
who they are]
 
E

Eric Sosman

Nick said:
How do you know for sure that you cannot allocate more memory? Perhaps your
program has some caches that can be flushed, or some state than can be
reduced. malloc returning NULL does not necessarily have to result in the
termination of your program. For instance, should the whole server [go?]
down because malloc returns NULL? I think not... Therefore, malloc returning
NULL is NOT necessarily a _fatal_ error, well, IMVHO at least...

again, I know these things *could* be done but does anyone actually do
so?

[actually, it's a pretty safe bet that *someone* on clc does, I'm just
curious
who they are]

I'm one of them.

In an interactive editor-like setting, if the user says
"Load file huge.dat" and malloc() can't find space for it,
there's no reason to panic. Just tell the user the file's
too big, return to the status quo ante, and await further
instructions.

In a multi-client server-like setting, if one client's
request exhausts memory there's no reason for all the clients
to suffer for it. Just bounce one client with "Server too
busy; try later" and allow the others to make use of the
memory his session used to own. (There's some ambiguity
about which session is "guilty;" see many discussions of O/S
policies that offer more memory than they can deliver.)

... and so on. A general-purpose low-level routine like
malloc() or fopen() cannot know the global consequences of
the failure it reports, and so should not take actions with
global consequences in response to failure. A purpose-built
wrapper for a particular program might do so: If you're
writing a program where you know out-of-memory is invariably
fatal and there's no special cleanup required, there's no
harm in writing a malloc_or_die_trying() wrapper. Just don't
call it from your general-purpose hash table package ...
 
N

Nick Keighley

<OT>
Incidentally, Nick, I tried sending you an email, removing _nospam
from your From:, but it bounced. Could you possibly send me an email
containing your genuine address? (See below for my address.)
</OT>

the email address *is* genuine. Don't remove the "nospam"
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
This line unintentionally left unblank

and google may have munged your email as I couldn't get
a usable email address out of it

I'm convinced some sort of global communications snafu
is what does for us in the end.
 
B

Barry Schwarz

The malloc() returned NULL, then what I am supposed to do, check again
for NULL return value from my_malloc() ? If I need to check the
return value then why would I create my_malloc(), I will just call
malloc() directly there and check it. I just wanted to reduce the
number of lines being used in function.

malloc returns NULL when if fails. Your wrapper function checks for
this, calls fprintf, and THEN RETURNS THE NULL TO THE CALLER. If the
calling function doesn't also check (yes it is a duplicate check), it
will invoke undefined behavior whenever malloc returns NULL. So the
question is, does your wrapper save any lines if the functions which
call the wrapper need to check also. If your wrapper aborted the
program (not recommended in general but maybe appropriate for the
project you are currently working), then your calling function would
not need to duplicate the check.

As it stands now, your calling function has no idea if the wrapper (or
more properly malloc) succeeded so you have not reduced anything in
the calling function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top