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

Pages: 1-4041-

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

Name: Anonymous 2010-06-29 16:46

On a desktop/home computers you practically never get NULL from malloc, unless your program has a severe memory leak, since the operating system will swap unused memory to disk. Also, memory fragmentation might cause malloc() to fail if you ask for a block too big even though there's theoretically free memory left.

When the memory has gotten fragmented, you'll notice that performance drops since malloc() has to do a lot of work per allocation.

Name: Anonymous 2010-06-29 17:01

>>41
Your kopipe is out of date.

Name: 29 2010-06-29 21:50

>>34
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.

Sure, but these aren't considered stable by any safety-critical standard. Without managed pointers, any sort of malloc implementation is vulnerable to fragmentation. This is why even the latest versions of Firefox grow to using many hundreds of megs of RAM over the course of several days of use. With managed pointers, you need low-level thread control or some sort of stop-the-world call to compact memory, preventing any real-time application. You also need some extreme static analysis to guarantee an upper limit on dynamic memory usage (hint: no such analysis currently exists.) And you cannot reliably estimate performance of any kind. These are not stable or safe; they are merely acceptable for consumer applications.

There is a reason that safety critical coding standards, e.g. http://spinroot.com/p10/rule3.html , forbid dynamic memory allocation after startup. You don't want your plane to crash or nuclear reactor to fail because its memory was too fragmented.

Name: Anonymous 2010-06-29 22:13

>>43
The flaw in your reasoning is that a web browser isn't a nuclear reactor. It neither needs to nor can know how much memory it will need for correct operation. I'm all for abolishing the browser, but not for that reason.

Name: Anonymous 2010-06-29 22:30

>>44
The flaw in your reasoning is that a web browser isn't a nuclear reactor.
Hmm. This is not immediately obvious to me.

Name: Anonymous 2010-06-29 22:32

>>43
Funny thing, Firefox has lots of trouble with memory, whereas Opera, Safari, Chrome, hell, even MSIE perform much better in that respect. You can blame malloc all you want, but the problem is the browser.

Name: Anonymous 2010-06-29 22:35

[spoiler] fuck [spoiler]

Name: Anonymous 2010-06-29 22:38

>>45
Oh, you're an engineer. My condolences.

Name: Anonymous 2010-06-29 23:06

This discussion is silly since most software people develop these days isn't meant to run on extremely limited embedded systems or ``safety-critical'' systems. Most software should be written in as general manner as possible and only specialized as needed and when needed, not done so by default. Doing so by default only greatly cripples the application.

It reminds me of one system which I have much respect for, but it pre-allocates all the heap on startup, then just uses its own allocators and gc to operate on that heap. This is stupid because I have a fast machine with a lot of RAM, and it needlessly wastes RAM which it doesn't need by default, but when I have it load applications which alloc a lot, it would need a lot more, thus either fail because of heap exhaustion(read: allocation failure) or it would extend its heap automatically or via a command line parameter (depending on used options). Virtual memory exists for a reason on server and desktop machines. Manual memory allocation exists for a reason and GCs exist for a reason. They provide robust applications in the real world for real applications. What you consider ``safety-critical'' is just niche domain, but a needed one nonetheless, but it doesn't apply to most software written for normal boxes, nor it should.

Besides, failure to allocate memory is just one of many possible failures. I'd argue being able to recover the application automatically or manually (interactively) is of much higher value than just avoiding memory allocation at a cost. Here's an example where NASA launched a spacecraft into space, and upon extraordinary circumstances managed to patch the system live and fix the bug using a REPL (the application, Remote Agent, was a sort of a control AI, written in Lisp):

https://www.globalgraphics.com/news/ggpress.nsf/GGRVPressReleasesPublished/06608A7E4A25BE15802568E1005745C8/$FILE/PR19990817a.pdf
http://ti.arc.nasa.gov/m/pub/archive/2000-0176.pdf
http://en.wikipedia.org/wiki/Deep_Space_1

I'd feel a lot more comfortable as an engineer to be dropped in a REPL when a critical error happens so I could debug, find the error, and fix/hotpatch the system as it runs and resume its workings without interruptions, than I would be to be greeted by a segfault and eventual catastrophic crash because there was a bug someone didn't anticipate (suprise: humans aren't perfect, and foolproof programs don't exist. if it can fail, it will fail given enough time and entropy)

Name: Anonymous 2010-06-30 0:02

http://www.schneier.com/blog/archives/2010/05/automobile_secu.html
Some interesting reading in the comments here about secure systems.

Name: Anonymous 2010-06-30 10:07

Name: Anonymous 2010-06-30 14:51

>>51
hl=en&aq=f&aqi=&aql=&oq=&gs_rfai=
Son... I am disappoint.

Name: Anonymous 2010-06-30 15:42

>>43

p10 even denying alloca? Man, that's rough. Are you allowed to do any IO? Although, I admit I wouldn't want to fly on an Airbus that had a flight control system wihtout real time constraints.

Name: Anonymous 2010-06-30 17:35

>>53
Everyone should deny alloca. It's horrible for many reasons.

Name: 43 2010-07-01 19:00

>>44-46
Strange how you guys thought my post was in any way related to a web browser. As I've been saying, malloc is perfectly fine (and indeed useful) for consumer applications. These are not safety-critical (no lives are at stake), and not expected to remain stable over a period of years or decades.

>>49
Of course a remote firmware update is useful. That also has absolutely nothing to do with malloc. I'd bet dollars to donuts that spacecraft already did not allow dynamic allocation of any form.

Name: Anonymous 2010-07-01 19:23

>>54
There's nothing alloca can do that ordinary variable declaration can't. Why does it even exist?

Name: Anonymous 2010-07-01 19:55

>>56
C89 and C++ don't support VLAs. Also, VLAs are almost as dangerous as alloca()...

Name: Anonymous 2010-07-02 2:26

>>53,54
It's the implementation of alloca() that's bad, combined with C's lack of stack protection.

In a language with segmented stacks and/or better static analysis to guarantee stack limits, alloca() is a great idea (and perfectly safe.) Unfortunately I don't think any such language actually exists. Go and D come close...

Name: Anonymous 2010-07-02 2:49

stack allocation is dumb. IF you need that kind of performance you statically pre-allocate a chunk of memory.e.g. char a[100000];

Name: Anonymous 2010-07-02 2:58

>>57
VLAs don't have to be on the stack. You don't even need a stack at all to implement C.

alloca only exists for the convenience of not having to use free. It is intended to be used for the sort of quick hacks that competent programmers would write in perl (the kind that take seconds to write, and are only run once or twice before being discarded).

Name: Anonymous 2010-07-02 3:14

>>60
You don't even need a stack at all to implement C.
Oh, that's not true. As long as there is recursion involved, you need to have some kind of LIFO structure. It does not matter whether you call it stack or something else, it will still be the stack.

And don't come up with this "C specification does not mention stack" bulshitte.

Name: Anonymous 2010-07-02 3:14

>>60
You don't even need a stack at all to implement C.
Oh, that's not true. As long as there is recursion involved, you need to have some kind of LIFO structure. It does not matter whether you call it stack or something else, it will still be the stack.

And don't come up with this "C specification does not mention stack" bulshitte.

Name: Anonymous 2010-07-02 3:33

>>62
Last I checked the specification doesn't specify how you should implement recursion- just how it should work.

Name: Anonymous 2010-07-02 5:02


T *foo;
if (!(foo=malloc(TIMES * sizeof *foo))) {
   perror("malloc()");
   exit(EXIT_FAILURE);
}

Name: Anonymous 2010-07-02 7:04

>>62
that's been discussed to death on comp.lang.c:
Before you repeat that the claim, which has been frequently made in this thread, that LIFO semantics are mandatory, please consider the following implementation:

It allocates and deallocates space for activation records. It makes sure that it always allocates a given record before the start of the lifetime of the variables stored in that record, and it makes sure that it never deallocates them until after the end of the lifetime of those variables, but it does not always carry out the allocations and deallocations in the same order as a LIFO mechanism would.

What requirement of the C standard would such an implementation violate?

This question is interesting because it relies only on the text of the Standard, and tells something about all possible C implementations. The Standard does not define the term "stack", as has been said, but we can certainly make inferences from the text of the Standard. The Standard's requirements on the lifetime of variables are very loose, and if the implementation wishes, it can make every variable exist from the start to the end of the program. Even the case of multiple instances of local variables in a recursive function can be catered for when we realise that C doesn't guarantee infinite recursion depth.

I can also imagine a C implementation which provides closures as an extension and as a result has a "spaghetti stack" which is certainly not a true stack. I believe this shows that C does not require a stack.

Also, what about an implementation that uses two stacks, one for return addresses and a separate stack for automatic variables? This could fully conform and would have major advantages, such as preventing buffer overflows from overwriting the return address. On such an implementation what would you mean by "the stack"?

Name: Anonymous 2010-07-02 7:14

Name: Anonymous 2010-07-02 7:15

>>66
it'd be better to link to the beginning of the thread instead of the middle of it:
http://groups.google.com/group/comp.lang.c/browse_thread/thread/39a0658c686dce82/680d40637eab95e3

Name: Anonymous 2010-07-02 7:57

>>67
Cheers, my Home and PgUp keys don't work anyway.

Name: Anonymous 2010-07-02 8:21

>>65
I can also imagine a C implementation which provides closures as an extension and as a result has a "spaghetti stack" which is certainly not a true stack. I believe this shows that C does not require a stack.

AKA Apple's Blocks (all hail Glorious Leader Jobs)

Name: Anonymous 2010-07-02 8:40

>>60
VLAs don't have to be on the stack. You don't even need a stack at all to implement C.
Uh? >>57 did not say anything about a stack. >>58 mentions the stack, and says nothing about VLAs. Are you confused?

Also, your blatant Perl plug is ludicrous. alloca() is useful for performance. When you just need a scratch buffer, malloc() is by comparison extremely slow, leads to memory fragmentation, and will give you space in a different cache line. alloca() is compiled into a single processor instruction to offer you the space you need, and the space is (likely) already in the processor cache.

In fact absolutely everything in your post is wrong. Hand in your geek card; no internets for you today.

Name: Anonymous 2010-07-02 8:44

>>70
geek
  ( ˃ Д˂)

Name: Anonymous 2010-07-02 8:56

Uh? >>57 did not say anything about a stack.
apparently you missed the mention of alloca in >>57. You might want to work on your reading comprehension skills.

alloca() is useful for performance.
If malloc is too slow, use sbrk or mmap. If you'd actually written anything of consequence, you'd know that if you use malloc sensibly, it's almost never too slow.

malloc() is by comparison extremely slow, leads to memory fragmentation, and will give you space in a different cache line
That's only if your malloc is complete shit (the slow and different cache line things) and you're using it wrong (the memory fragmentation thing).

Name: Anonymous 2010-07-02 10:37

>>72
write a program which uses malloc and have it beat one with statically allocated block of memory. Then we can talk.

Name: Anonymous 2010-07-02 14:11

I think >>72 is trollin' y'all.

Name: Anonymous 2010-07-02 14:43

If malloc is so bad, wouldn't everyone want to write performance critical parts without malloc/kmalloc/alloca/etc?

Name: Anonymous 2010-07-02 14:45

>>75
I bet you don't understand how even one of those works.

Name: Anonymous 2010-07-02 15:27

>>73
That's not what alloca does.
Also, that's trivial to do, just malloc a big enough block of memory once and it shouldn't be any slower than statically allocating the memory unless your malloc is designed to be slow on purpose.

Name: Anonymous 2011-02-04 18:19

Name: Anonymous 2011-02-04 19:06


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