Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

assert ( malloc...

Name: Anonymous 2010-06-28 13:36

A question for you, Anon.

If you watch at malloc() manpage you can notice that the function may return NULL in some cases (i.e. errors or 0-sized allocation). How do you face this issue?

I noticed that many programmers check the return value and manage error routines for it, while other just assert() the return value not to be NULL.

Also in C++ by the way you use the new operator without taking care about the return value (I guess it's asserted to be not NULL under the hood, is it?)

What is your opinion?

Name: Anonymous 2010-06-28 13:40

In simple programs I just assume the return value to be non-NULL (that is, if I'm using C).
And an assert would be fine, too; in most programs you can't really handle an out-of-memory exception, because it doesn't depend on the program itself.
Of course, business applications/mission-critical software should properly take care of everything.

Name: Anonymous 2010-06-28 13:41

assert() is for debugging. It's a ham-fisted `error routine' (if it can even be called that). It shouldn't ever find its way into production code.

Name: Anonymous 2010-06-28 13:41

Anon doesn't live here, dude.

Most people don't bother checking the return value of malloc, because in most cases there's no meaningful way to recover from an inability to allocate memory, so you might as well let the whole thing segfault.

Name: Anonymous 2010-06-28 13:42

Name: Anonymous 2010-06-28 13:47

Yeah dude, if malloc fails, the users is fucked as you may as well bring his whole pc down

Name: Anonymous 2010-06-28 13:48

>>4
Ok, but at this point I guess it's more delicate to assert-abort instead of getting segfault... segfault has a buggy-program fashon...

Name: Anonymous 2010-06-28 13:49

[code]
foo = malloc(sizeof(*foo));
if (foo == NULL) {
    system("shutdown -h now");
}

Name: Anonymous 2010-06-28 13:57

Yeah, the only thing difference is that a segfault might show up as the programers error and a error message will simply show that the OS/PC fucked up.

Name: Anonymous 2010-06-28 13:59

[/code]

Name: Anonymous 2010-06-28 14:16

while (!(data = malloc(DATA_SIZE)));

Name: Anonymous 2010-06-28 14:24

Use Linux, where malloc doesn't fail.

Name: Anonymous 2010-06-28 14:26

MALLOC MY ANUS

Name: Anonymous 2010-06-28 14:26

assert(" Download more ram!")

Name: Anonymous 2010-06-28 14:48

>>1
In C++, the new operator is guaranteed to evaluate to a valid pointer, else it throws an exception (I'm to lazy to look up which).

Name: Anonymous 2010-06-28 14:56

Wrapping your mallocs in asserts is not a good idea, as if NDEBUG is defined, the assert macro (and thus your malloc call) may be removed at compile time.

>>12
It will, once you've exhausted your address space.

Name: Anonymous 2010-06-28 15:03

>>15
Thanks for the info, bro. I very appreciated that.

Name: Anonymous 2010-06-28 15:41

>>16
Luckily, in a modern 64-bit machine, you'll experience other debilitating symptoms well before you exhaust the address space...

Name: Anonymous 2010-06-28 17:38

>>1
Most people just don't bother checking. This is especially common in C++ where people disable exceptions (so new has no way to signal failure). In my opinion this is a terrible way to program. It's fine for desktop where you have swap and a shitload of memory, but it's completely wrong for embedded.

The way to do it correctly is that any operation that could fail should return a flag that says whether it failed, and the caller should always check this flag. If the caller is unable to handle it, it should also return an error code, and so on until someone in the call stack is able to handle it (usually by notifying the user that the operation failed.)

This does take some work to do, but it's not a huge amount; it's not nearly so bad as people pretend it is. Personally I think most developers sing the praises of exceptions because they are lazy; they think exceptions allow them to write no error handling code. In my experience writing everything with RAII and smart pointers is far more difficult, time consuming and error prone than simply returning and checking error codes.

It's also possible to test it rigorously; see e.g. how SQLite tests random malloc failures: http://www.sqlite.org/malloc.html , section 2.0.

Name: Anonymous 2010-06-28 17:56

>>19
If you want a stable system you have to do away with dynamic memory allocations altogether.

Name: Anonymous 2010-06-28 20:24

This is how I roll.

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

jmp_buf
thegamelol;

void suss()
{
  char *mander = NULL;
  long long timeago = 1;

  for(;;){
    char *expert_realloc_use = realloc(mander, ++timeago);
    if(!expert_realloc_use)
      longjmp(
thegamelol, 1);
  }
}

int main(void)
{
  if(setjmp(
thegamelol)){
    fputs("lolz\n", stderr);
    return 1;
  }

  suss();

  return 0;
}

Name: >>21 2010-06-28 20:26

oh and insert
mander = expert_realloc_use;
somewhere.

also I found another shiiichan bug with
jmp_buf thegamelol;
There was a space there when I entered it.

Name: Anonymous 2010-06-28 20:34

>>22
It strips spaces at the end of code blocks.

Name: Anonymous 2010-06-28 21:46

void *malloc_e(size_t size) {
 void *ptr;
 if(!(ptr=malloc(size))) {
  fprintf(stderr,"memory allocation error: %s\n",strerror(errno));
  exit(-1);
 }
 return ptr;
}

Name: Anonymous 2010-06-28 22:10

from my common.h:
/*
  new_malloc: addition to regular malloc that
  reports and error and exits whenever malloc
  returns a NULL pointer.
*/

static inline void *new_malloc (size_t alloc_size)
{
  void *temp_pointer;

  temp_pointer = GC_malloc (alloc_size);

  if (temp_pointer == NULL)
    {
      fprintf (stderr, "Could not allocate block of size %d, exiting.\n", alloc_size);
      exit (EXIT_FAILURE);
    }

  return temp_pointer;
}

/*
  new_realloc: like new_malloc except exits and
  reports when realloc returns returns a null
  pointer.
*/

static inline void *new_realloc (void *to_resize, size_t alloc_size)
{
  void *temp_pointer;

  temp_pointer = GC_realloc (to_resize, alloc_size);

  if (temp_pointer == NULL)
    {
      fprintf (stderr, "Could not allocate block of size %d, exiting.\n", alloc_size);
      exit (EXIT_FAILURE);
    }

  return temp_pointer;
}

/*
  macros to replace all mallocs with new_malloc
  and all reallocs with new_realloc.
*/

#define malloc(alloc_size) new_malloc (alloc_size)
#define realloc(to_resize, new_size) new_realloc (to_resize, new_size)
#define free(to_free) GC_free (to_free)

Name: Anonymous 2010-06-28 22:57

>>24
Bitches don't know bout my perror().

Name: Anonymous 2010-06-29 1:51

malloc() never failed me.

Name: Anonymous 2010-06-29 2:04

>>18
Unless I have, say, 512MB total in my 64-bit machine and request >512MB.
OH SHIT!

Name: 19 2010-06-29 2:40

>>28
No, on Linux it may still return a valid pointer. Your app may even work properly, since it can page to swap. It will only crash if you actually attempt to read/write to more pages than are physically available.

Apparently certain apps (e.g. sendmail) relied on this functionality. On startup it would allocate, say, a two gig chunk of scratch memory to use for internal allocations. Usually it would only use a small portion of this, so even if you only have 512 MB of ram, it would still work perfectly fine.

>>20
Yeah pretty much. This is also why I *hate* string libraries like bstring and std::string. If something malloc()s I want to damn well know about it!

Personally I'm a big fan of the rule of no allocations outside of app startup. Unfortunately this usually leads to the C programmer's disease, but if you do it right this can be managed.

This isn't really suitable for most applications though. I've often thought about how I would write something like a word processor. I think allowing malloc() strictly on startup, document load, and inputting/pasting text would be okay. In those three situations you could conceivably propagate up an allocation failure, telling the user to close some open documents to free memory. Of course you could also allocate a fixed block of memory and page in and out sections of the document as needed, so there is no reason you should need to malloc() at all.

Maybe I'm just behind the times. Everybody's wristwatch is going to have gigs of RAM soon, so why am I still bothering with this malloc() bullshit?

Name: Anonymous 2010-06-29 2:59

>>28
kill yourself, please

Name: Anonymous 2010-06-29 5:46

>>24 how a BSD programmer would write it
>>25 how a GNU programmer would

Name: Anonymous 2010-06-29 10:46

>>31
OpenSSH:
void *
xmalloc(size_t size)
{
    void *ptr;

    if (size == 0)
        fatal("xmalloc: zero size");
    ptr = malloc(size);
    if (ptr == NULL)
        fatal("xmalloc: out of memory (allocating %lu bytes)", (u_long) size);
    return ptr;
}


libiberty (gcc -liberty):
void
xmalloc_set_program_name (const char *s)
{
  name = s;
#ifdef HAVE_SBRK
  /* Win32 ports other than cygwin32 don't have brk() */
  if (first_break == NULL)
    first_break = (char *) sbrk (0);
#endif /* HAVE_SBRK */
}

void
xmalloc_failed (size_t size)
{
#ifdef HAVE_SBRK
  extern char **environ;
  size_t allocated;

  if (first_break != NULL)
    allocated = (char *) sbrk (0) - first_break;
  else
    allocated = (char *) sbrk (0) - (char *) &environ;
  fprintf (stderr,
       "\n%s%sout of memory allocating %lu bytes after a total of %lu bytes\n",
       name, *name ? ": " : "",
       (unsigned long) size, (unsigned long) allocated);
#else /* HAVE_SBRK */
  fprintf (stderr,
       "\n%s%sout of memory allocating %lu bytes\n",
       name, *name ? ": " : "",
       (unsigned long) size);
#endif /* HAVE_SBRK */
  xexit (1);
}

PTR
xmalloc (size_t size)
{
  PTR newmem;

  if (size == 0)
    size = 1;
  newmem = malloc (size);
  if (!newmem)
    xmalloc_failed (size);

  return (newmem);
}

Name: FrozenVoid 2010-06-29 10:58

If the malloc failure is caused by my program i would fix it instead of adding debugging layers, asserts, error reports to microsoft and similar half-baked "solutions".


__________________
Orbis terrarum delenda est

Name: Anonymous 2010-06-29 11:05

>>29
Yeah pretty much.
Really? I thought he was trolling. Dynamic memory allocation is very important in my opinion. It's so important that people have spent quite a lot of time working on components to handle the process so you don't have to.

Name: Anonymous 2010-06-29 13:26

Enjoy your AIDS AND FAIL, /prog/

Name: Anonymous 2010-06-29 14:07

>>34
You should be able to see where that got us.

Name: Anonymous 2010-06-29 14:29

>>36
I'm glad you live in a world where you can know everything that's going to happen before it happens, but I live in the real world where things are unpredictable, and systems need to be put in place to accommodate for uncertainty.

Name: Anonymous 2010-06-29 14:36

>>37
In many systems you can know what sizes your inputs will have, in other cases, you will probably have to use some dynamic allocation.

Name: Anonymous 2010-06-29 14:48

>>34 Yeah, Dynamiic memory allocation IS important.

Name: Anonymous 2010-06-29 16:20

>>34-39 samefriend

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List