xmalloc string functions

C

CBFalconer

Malcolm said:
The problem is, what is fixitup() going to do? Probably it needs
access to objects within the function's local scope to clean up.
So it cannot be a general-purpose function.

Sure it can. If you pass it what I suggested it can do anything
that the original malloc call did (including recalling malloc).
If, on return from fixitup, ptr is still NULL fixitup didn't
succeed. Now you can abort.
 
C

CBFalconer

Malcolm said:
Thank you. The rubbish that some people are posting to this
thread is quite unbelievable.

If you carefully examine the message, I believe you will find that
Ben has confirmed the accuracy of the documentation, which states
that "malloc failure terminates the application" or similar. So
there is never any opportunity to correct, save, etc.
 
C

CBFalconer

Flash said:
Kelsey Bjarnason wrote:
.... snip ...

It telling me it cannot open another windows is fine, killing the
word processor and all the other documents would not be. I
*expect* to find I don't have the memory to do some things
sometimes and have to close down one of the many things I am doing.


Indeed.

Well, the solution is simple. Give him an up-to-date fully
expanded CPM-80 machine, with 64 kBytes of memory, 2 full size 241
kByte 7" floppy drives and a 2 MHz 8080, running WordStar. :)
 
M

Morris Dovey

CBFalconer said:
Well, the solution is simple. Give him an up-to-date fully
expanded CPM-80 machine, with 64 kBytes of memory, 2 full size 241
kByte 7" floppy drives and a 2 MHz 8080, running WordStar. :)

Umm - do you cut down 8" floppies or stretch the 5-1/4" ones? :-D
 
K

Kelsey Bjarnason

[snips]

But, it's easy to avoid a bug in your application caused by that bug,
once you actually do read docs. If you can think, you'll notice the
obvious contradictions.

Gee, wasn't that the point, that there *are* contradictions? Well
imagine that, if you think, you can notice the very thing I've been
talking about. How surprising.
Massive inconsistency, huh? This is not true.

Yes, it is. It implies there are, or will be, library functions which do
_not_ abort on allocation failure, yet we also know there are library
functions which _do_, so we have two absolutely contrary manners of
dealing with the same problem, in the same library.

In exactly what universe is that considered *consistency*?
*You* certainly shouldn't use glib, since you won't read documentation
of the functions you are using

Wrong again. It is precisely *because* I read the documentation that I
recognize the inconsistency.
BS. Imaginary inconsistency.

No, a very real one. Read the documentation.
 
M

Malcolm McLean

CBFalconer said:
Sure it can. If you pass it what I suggested it can do anything
that the original malloc call did (including recalling malloc).
If, on return from fixitup, ptr is still NULL fixitup didn't
succeed. Now you can abort.
If fixitup is a function does it need to take the address of ptr as a
parameter so it can set it to whatever value it has fixed up?
 
M

Malcolm McLean

CBFalconer said:
If you carefully examine the message, I believe you will find that
Ben has confirmed the accuracy of the documentation, which states
that "malloc failure terminates the application" or similar. So
there is never any opportunity to correct, save, etc.
So these apps would be improved by replace the malloc() calls with
xmalloc().
 
S

santosh

Malcolm said:
So these apps would be improved by replace the malloc() calls with
xmalloc().

How? It's xmalloc() that makes it harder for the caller to implement
fix-up and continue strategies than malloc(). As you youself have said
several times, it's /possible/ to use xmalloc() just like malloc(), but
then most of the purpose of using it is defeated.
 
M

Malcolm McLean

santosh said:
How? It's xmalloc() that makes it harder for the caller to implement
fix-up and continue strategies than malloc(). As you youself have said
several times, it's /possible/ to use xmalloc() just like malloc(), but
then most of the purpose of using it is defeated.
In the xmalloc handler, you hog an emergency store of a few megabytes.
When memory fails, set a flag, and release the emergency store. If it fails
again, you must exit.
At a higher level, detect that the emergency store has been released, and
log the fact, closing down jobs or suggesting that the app be rebooted.
 
R

Richard Bos

But it's not true, there are ifs and buts. Using glib, you *can*
do stuff when malloc() fails. Yes, using glib all you sensibly
can do on malloc() failure is some sort of emergency work and
quit. If your application requires more, then you don't want to
use glib, that's it. But I claim that for 'regular' desktop
applications that is quite enough.

If your regular desktop application is a clock, perhaps. If it holds any
user input, and for this the application can be as simple as a
calculator, it is not nearly enough. Consider how irritating it would be
to type half a dozen numbers, of twenty digits each, and a handful of
operations, only to have your application crash because it could not get
the memory for that last comlpex calculation. At the very least, your
app should put up a message box saying "Out of memory - could not
compute", and then let you copy the previous twenty-digit result into
another document for safe keeping. But no, it crashed, taking not just
the final computation but also all intermediate results with it. Now you
have nothing, when you _could_ have had something to work from. Thank
you, glib.

Richard
 
M

Malcolm McLean

Richard Bos said:
If your regular desktop application is a clock, perhaps. If it holds any
user input, and for this the application can be as simple as a
calculator, it is not nearly enough. Consider how irritating it would be
to type half a dozen numbers, of twenty digits each, and a handful of
operations, only to have your application crash because it could not get
the memory for that last comlpex calculation. At the very least, your
app should put up a message box saying "Out of memory - could not
compute", and then let you copy the previous twenty-digit result into
another document for safe keeping. But no, it crashed, taking not just
the final computation but also all intermediate results with it. Now you
have nothing, when you _could_ have had something to work from. Thank
you, glib.
I agree. You should have the chance to close something else down. If there's
absolutely nothing you can close and the calculator is out of memory then
you are out of luck, but you are really stressing your machine in that case
and won't be able to work for long with it like that in any case.
At the moment, for instance, I've got outlook express open, which is holding
this. But I've also got Internet Explorer with a website I've just logged
out of, and a copy of MS Visual C++ Express. I could either of those with
minor inconvenience, if I really wanted that calculator result.
 
R

Richard Bos

Malcolm McLean said:
I agree. You should have the chance to close something else down.

No, the damned thing should not be crashing because of a mere lack of
memory in the first place. It should not be that incompetent.

Richard
 
F

Flash Gordon

Kelsey Bjarnason wrote, On 30/01/08 15:14:
Kelsey Bjarnason wrote, On 30/01/08 11:43:
[snips]

On Wed, 30 Jan 2008 00:29:48 +0000, Flash Gordon wrote:

Maybe for you. I, on the other hand, can be running three VMs eating
up a bit over three quarters of the memory, Lotus Notes, another email
client (yes, I have good reasons for using multiple email clients
simultaneously) and several other applications.
Likewise. This box has 2GB RAM installed, and it runs fairly often at
near capacity.
I'm glad I'm not the only one filling the RAM of a 2GB machine.
Actually, one of my colleagues is also finding the 2GB of RAM is rather
tight.

Depends what you do with it.

I do development on it. Sadly, at the moment, I'm doing Windows-based
development, meaning I'm running XP in a VM window. Slow as snail snot,
but it works - but it does suck ram.

I'm normally Linux in a VM. I'm often running both Windows and Linux in
VMs. Sometimes I'm running a couple of Windows sessions in VMs *and* a
Linux VM. I can think of good reasons I might want to run 3 windows VMs
and a Linux VM. All on my notebook ;-)
Besides that, I've got Apache, MySQL, Postgres, leafnode, I often have
postfix/cyrus/amavis/spamassasin plus their attendant doo-dads (pyzor,
razor, etc, etc) sucking up who knows how much memory, plus KDE which
usually ends up running umpteen apps - kmail, moz, pan, kdevelop, amarok,
kopete, skype and more, plus OpenOffice unless I'm really cramped for
space.

Adds up. :)

With me it is multiple VMs one of which is running MS SQL Server and an
application that runs against it, another running a Linux development
system, plus all the usual stuff on the real machine. I would like to
run a separate VM with the clients for the Linux and Windows based SW,
but that is *really* pushing it...

Yup, it adds up a lot :)
Indeed. It'd make me want to pay a little visit to the developer, and
bring along my buddy Guido and his pet iguana.

<snip>

I've got a nice stone axe...
 
H

Herbert Rosenau

There is nothing to recover because failure of fopen()
is a normal situation. Absolutely different from a failure
of malloc() when you are trying to allocate a structure
to push into the event queue to scroll text a bit later.

There is no difference at all. When I can't open a file I will tell my
caller that fact like I do when malloc() fails to delever me the
amount of memory I ask it for.

The caller will check the error condition it receives and will react
properly on that and then tell its caller the the error when it is
unable himself to recover from that error to continue as it should
when possible. Its caller does the same until there is a point that is
either
- action is complete undone - clean state
normal work goes on
- action is complete undone - no chance to to contine normal run
shut down program cleanly - a restart of the progam may be more
successfull

There is nothing that requires an abort() or exit() abnormally.

Sure, it costs a bit more to get a program failsave - but it saves
lots of money, lots of time and holds customer because no customer
will ever complain because the program aborts, looses or destroy work
or data only because the programmer was crazy enough to kill its
program only because there was a moment where an open() faild, there
was for a period of time not enough memory to allocate a small big or
very big amount of memory to get a single action done.

It makes always sense to check malloc() for success - because this
saves a lot of money for useless maintenance, earning annouyed
customers, ending up in loosing trust.


Strawman you see. We were talking about malloc() and
you tell my application will crash when fopen() fails.

Note that if your application can ask user about something,
then it does more than fopen(). If it can take any
action when fopen() fails, then it does more. That's
what I meant. cat utility doesn't have much to do
if it can't open the file it's supposed to read.
A gui application doesn't have much to do if it
doesn't have memory to draw stuff it draws.

This is completely false. Even a guy application can handle any lack
of memory well without the need to crash the whole app.


--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
Y

ymuntyan

There is no difference at all. When I can't open a file I will tell my
caller that fact like I do when malloc() fails to delever me the
amount of memory I ask it for.

The caller will check the error condition it receives and will react
properly on that and then tell its caller the the error when it is
unable himself to recover from that error to continue as it should
when possible. Its caller does the same until there is a point that is
either
- action is complete undone - clean state
normal work goes on
- action is complete undone - no chance to to contine normal run
shut down program cleanly - a restart of the progam may be more
successfull

There is nothing that requires an abort() or exit() abnormally.

What exactly are you talking about here? If you do shut down
the program then you do shut it down, that's it. Whether you
do it up the stack in the main() or in the memory allocator
may or may not be different. If it's not different, then it
1) doesn't make much sense to unwind the stack;
2) actually is more expensive to unwind the stack: the more
code the more bugs you got.
Where it's not true, it's not true.
Sure, it costs a bit more to get a program failsave - but it saves
lots of money, lots of time and holds customer because no customer
will ever complain because the program aborts, looses or destroy work
or data only because the programmer was crazy enough to kill its
program only because there was a moment where an open() faild, there
was for a period of time not enough memory to allocate a small big or
very big amount of memory to get a single action done.

It makes always sense to check malloc() for success - because this
saves a lot of money for useless maintenance, earning annouyed
customers, ending up in loosing trust.

Right, malloc() result must always be checked. Except it doesn't
imply your code must be cluttered with if() for every call to
whatever_func_you_use_to_allocate_memory().
This is completely false. Even a guy application can handle any lack
of memory well without the need to crash the whole app.

Right, it can. Except it can't draw if it doesn't have
memory to draw. I don't care if the application is still
up if it doesn't display the stuff it's supposed to display.
Nor do I care how it exits on OOM, using abort() or exit(0)
or exit(EXIT_FAILURE); does it exit from main() after everything
properly returned an error or right in the draw_thingie()
call (AFTER it properly cleaned up its crap, how about that?).

Yevgen
 
C

CBFalconer

Malcolm said:
If fixitup is a function does it need to take the address of ptr
as a parameter so it can set it to whatever value it has fixed up?

Yes. It was NULL.
 
J

Jeffrey Stedfast

Actually, it was usually Galeon/Gecko which leaked, or rather whose
leaks would begin to trigger out-of-memory errors. But that's beside the
point. I'd much rather that Evolution fail to open a message than to
exit entirely.


If these were the only choices (crashing applications or a frozen
screen), I'd be more agreeable.

There were many bad spots in Evolution, but mostly the code was OK (I've
combed through much of it). Evolution had to deal with bad UTF
encodings, malformed MIME, networks coming up and going down. Handling
memory allocation failures would hardly add much in the way of
complexity or effort.

As someone who has looked over what I would guess was Camel code (you
mentioned MIME, bad UTF encodings, etc) - you've likely seen that we (I'm
one of the main original 2 developers who wrote that code) were pretty
meticulous about checking error codes from syscalls everywhere.

We had some problems with g_malloc() abort()ing on failure, but a lot
(all?) of those problems were actually real programming errors (such as
trying to malloc some rediculously large amount of memory - e.g. in the
neighborhood of 4GB). Most of these sorts of problems occurred in the
IMAP provider of Camel (more than anywhere else in all of the mail code,
likely, but certainly in relation to the rest of Camel).

For example, when requesting messages from the IMAP server, we would
naively try to allocate a memory buffer using the size value provided in
the LITERAL response from the IMAP server. There were also a few places
that did some bad pointer arithmetic to arrive at negative values (which,
when cast to size_t are rather large ;-)

Before I moved on to more interesting projects, I started a complete
rewrite of the IMAP provider which you can find in the evolution-data-
server source tree under the `camel/providers/imap4' directory.

FWIW, glib also has g_try_malloc() and g_try_realloc() functions which
retain the original libc behavior of malloc/realloc.
I know for a fact that Evolution and similar applications have exited
because their malloc wrapper decided to exit. They've also crashed for
numerous other reasons. Bugs are bugs, but defective by design is hardly
excusable.

I wouldn't be surprised to learn that your experience was related to bad
arithmetic calculating the size of memory to allocate as opposed to
simply being out of memory. I'm fairly certain that's a far more likely
scenario than being out of memory for most users.

My point is that while, yes, perhaps Evolution would not have crashed as
a result of the malloc() call, it /probably/ would have crashed a few
instructions later due to the logic errors that contributed to the
original problem anyway.
Exiting on malloc failure makes sense for a utility like sort(1). It
doesn't make sense for desktop applications, unless there's a separate
strategy, like a multi-process configuration where a component exiting
is part of the design of handling errors and making a best-effort
recovery.

It makes sense for sort(1) because it categorically cannot perform its
task on a failure.

Many times this is also the case for applications.

Sometimes it is not appropriate, but sometimes it is.
And its practical because sort is usually just a
sub-component in a larger work. Sort can exit without killing the script
or application which called it.


Users are, sadly, inured to this issue. Nor can they discern the reason
for failure, so they aren't capable of judging the cost/benefit of any
particular behavior.

You sort of missed part of my point regarding Evolution. What I was
experiencing was a denial of service caused by processing untrusted
data.

true, but it could also be argued that prevention could (and should) have
been done prior to malloc'ing :)
And by using glib you have no recourse.

As mentioned above, there are g_try_malloc() and g_try_realloc()
functions.

While, granted, you don't have that option if you are trying to create a
widget and Gtk+'s use of g_malloc() fails, but you can certainly minimize
the problem by using g_try_malloc()/g_try_realloc() ... or god forbid,
malloc() and realloc() from libc instead.

Most likely if creating a widget fails, though, you're probably SOL
anyway - it would be a lot of work to handle this situation by shutting
down other parts of the application in order to make enough room to do
something useful, particularly if you don't have access to parts of the
application that would be ok to shut down.

You should also note that in order to allow application programmers to
handle all of these memory allocation failures properly would require a
more cumbersom widget toolkit API which would likely deter most non-paid
free software developers from developing applications using said toolkit.

If you don't believe me, just look at how few people actually error check
all of their syscalls in any real-world software you've ever read the
code for :)

If I got a penny for every unchecked malloc(), open(), read(), write(),
close(), or slew of other calls I ever saw in free software projects I've
looked over the code for, I'd be a very rich man.

Hell, I'd be a rich man just for the little amount of time I spend
reading code in this newsgroup :)

(come on, laugh, you know it's true ;-)
Indeed, much of glib's
functionality is simply a rehash of, by now, widely supported library
interfaces, but with the feature of exiting when memory becomes tight.

There's definitely a lot wrapper API around libc functionality... like
g_mkdir() and so forth (I guess this is needed for Win32 porting?
*shrug*).

The problem is that such a strategy is usually the wrong one for the
class of applications which glib serves: desktop applications,

I would tend to disagree depending on the situation in which the malloc
failed.

Perhaps that means we agree, but to me it sounds like you are saying it
is never ok to abort on malloc failures which I happen to disagree with.
and
increasingly network daemon services.

Well, network daemon services I would agree very much with - but network
daemons are usually a lot less complex and a whole different breed of
program than desktop applications.
Both of those usually involve
monolithic applications doing complex tasks for which memory allocation
failure is only one of dozens or hundreds of exceptional conditions. And
yet out of all of them people will argue memory allocation alone can be
completely ignored, simply because it's too burdensome.


It's not science fiction. It's just difficult. And sometimes the answer
involves not using C, rather than using C and choosing not to address
the problem.

This is definitely true.

Being able to throw an exception, for example, in a language like Java,
c++, or heaven forbid, C# definitely gives the programmer better options
for achieving proper error handling for memory allocation failures.

Unfortunately, it's not always trivial to do so in large applications
written using C.

A strategy you might find many application developers take is that of
periodically saving user-data as a precautionary measure to avoid data
loss should the application unexpectedly exit (due to a g_malloc()
failure or any number of error conditions that may not be accounted for).

I would personally love to see a large desktop application written (in C)
that handles all malloc() failures properly as some (presumably non-
application developers) in this thread have been dictating. It would be a
learning experience for me and I would greatly appreciate learning new
techniques :)

Jeff
 
J

Jeffrey Stedfast

If your regular desktop application is a clock, perhaps. If it holds any
user input, and for this the application can be as simple as a
calculator, it is not nearly enough. Consider how irritating it would be
to type half a dozen numbers, of twenty digits each, and a handful of
operations, only to have your application crash because it could not get
the memory for that last comlpex calculation. At the very least, your
app should put up a message box saying "Out of memory - could not
compute"

what if the system doesn't even have enough memory to pop up such a
dialog? Likely it'd take far more resources to display said dialog than
it would take to make the calculation ;-)
, and then let you copy the previous twenty-digit result into
another document for safe keeping.

ah, but that also requires a clipboard memory buffer be allocated... but
you have no memory left ;-)

Sorry to be a smart-ass here, but you clearly have not thought about this
problem in the context of the average desktop application.

In a small daemon, if you get a malloc() failure, you have a lot more
options open to you than you do in a graphical desktop application
because you can do a lot more with very small amounts of memory (or none
at all).

A few examples:

- start dropping idle client connections (which would likely not require
any /new/ allocations) until you have enough memory to do the critical
operation you need to do

- print an out-of-memory or "sorry, can't do that right now" error to the
client socket (or terminal) which would likely not require any new memory
allocations (error strings could be static)

- wait until memory becomes available


On the other hand, say, a word processor application, if the user
requests some sort of action and a malloc() fails for 12 bytes, what is
it supposed to do?

If the documents the user has open have already-opened file descriptors,
the app might be able to save them before going down - but:

1. it certainly doesn't have the option of displaying an error dialog.

2. if any of the files are unnamed or otherwise would require any of:

a) filename generation (would require string building)
b) file descriptor opening (which takes memory)
c) user-interaction (this one is right out)

the application would certainly not be able to save the documents at that
point...

3. can't simply wait because that would be a "hang" which is likely to
cause the user to kill it anyway.
But no, it crashed, taking not just
the final computation but also all intermediate results with it. Now you
have nothing, when you _could_ have had something to work from. Thank
you, glib.

Richard

Feel free to fix it?

Oh wait, I forgot that this whole thread is actually a pissing contest
more than anything else, so that people who don't actually write desktop
applications can feel superior to those who do.

Jeff
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top