lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, May 01, 2015 at 09:53:57PM +0800, ???? Cloud Wu wrote:
> > In my experience malloc does fail and quite often when running on a system
> > with constrained memory. I see a lot of code with unchecked mallocs on
> > github
> > and I don't like it. If it's too much effort to check return values why not
> > just wrapper malloc/calloc so OOM failures set a message and exit cleanly?
> 
> I would like implement the main function first, and then write the
> details about these checks.
> 

Handling allocation failure isn't a detail. Adding that later will be much
more bug prone because proper handling often depends on the details of how
you maintain data structure consistency. There can be hidden dependencies
that you'll forget about later, leaving dangling pointers, inconsistent
locks, and other nastiness.

In the context of Lua it's even more important. Almost any call into Lua
could trigger an exception. Anytime you call into Lua, all your C data
structures should be in a safe state--initialized and anchored in the Lua VM
object graph (to prevent leaks). That requires careful ordering of your C
statements. For example, this code is wrong

	FOO *foo = NULL, **fp;
	int error;

	foo = foo_create(&error);
	if (!foo)
		goto error;
	fp = lua_newuserdata(L, sizeof *fp);
	*fp = foo;
	luaL_setmetatable(L, "FOO*");

because lua_newuserdata could throw an exception, causing your foo object to
leak. Or luaL_setmetatable could throw before attaching the proper __gc
handler to the userdata object, also causing a leak. Better code does

	fp = lua_newserdata(L, sizeof *fp);
	*fp = NULL; /* __gc should handle NULL properly */
	luaL_setmetatable(L, "FOO*");
	*fp = foo_create(&error);
	if (!*fp)
		goto error;

IMHO, decide now: implement state unwinding, or make it policy going forward
that OOM is not something you'll ever handle. Putting it off is the worst
choice of all.