Latest from the blog

Dangers of lua_error when using C++

Dangers of lua_error when using C++

By default Lua uses longjmp when lua_error or luaL_error is called, this can produce subtle bugs or memory leaks in C++ if you are not careful.

Take the following code, which simply calls the foo function which creates an object on the stack and throws an error:

   1  #include <iostream>
   3  extern "C" {
   4      #include "lua.h"
   5      #include "lualib.h"
   6      #include "lauxlib.h"
   7  }
   9  class Obj {
  10  public:
  11      Obj() {
  12          std::cout << "object create" << std::endl;
  13      }
  15      ~Obj() {
  16          std::cout << "object destroy" << std::endl;
  17      }
  18  };
  20  int foo(lua_State*L) {
  21      Obj obj;
  22      return luaL_error(L, "error in foo");   
  23  }
  26  int main(int argc, char** argv) {
  27      lua_State* L = lua_open();
  29      lua_pushcfunction(L, foo);
  30      int r = lua_pcall(L, 0,0,0);
  32      if (r == LUA_ERRRUN) {
  33          std::cout << lua_tostring(L, -1) << std::endl;
  34      }
  36      lua_close(L);
  37      return 0;
  38  }

When compiled against the default build of the Lua library and run you get the following output:

$ g++ main.cpp -llua -o example
$ ./example 
object create
error in foo

Notice the destructor was never called on obj. However if you build Lua as C++ then lua_error() will be implemented using C++ exceptions which will cause the stack to clean up as expected.

On my Mac I built Lua as C++ with the following command:

make macosx -e CC=g++

I’ve built Lua on Windows as C++ as well, in Visual Studio there is a setting to compile sources as C++ rather than by file extensions which is the default. Now when building and running you get the output you would expected:

$ g++ main.cpp -llua -o example
$ ./example
object create
object destroy
error in foo

One other thing to note is that the extern “C” around the Lua includes is no longer needed after building the Lua library as C++. If you can’t rebuild the Lua library for some reason or another than you just need to be aware and make sure everything is cleaned up before calling lua_error() or luaL_error().

Comparing Ruby Fibers to Lua Coroutines

Comparing Ruby Fibers to Lua Coroutines

One of the more interesting features of Lua are coroutines. One of the new features in Ruby 1.9 are fibers which are exactly the same thing, in fact they even borrowed the resume/yield method names from Lua. The following Ruby code:

   1  fib = do  
   2      x, y = 0, 1 
   3      loop do  
   4          Fiber.yield y 
   5          x,y = y,x+y 
   6      end 
   7  end 
   9  20.times { puts fib.resume }

is roughly equivalent to the following Lua code:

   1  fib = coroutine.create(function()
   2      local x, y = 0, 1 	
   3      while true do
   4          coroutine.yield(y)
   5          x,y = y,x+y 		
   6      end
   7  end)
   9  for i=1,20 do
  10      local _, value = coroutine.resume(fib)
  11      print(value)
  12  end

Introducing luaspec

Introducing luaspec

I’ve been doing a lot of work with Lua over the past couple of years. Originally I used luaunit for unit testing. This has worked ok, but I’ve used RSpec while working with Ruby and have come to appreciate the specification style syntax and the different mindset it invokes while writing tests. So I introduce to you luaspec, a behaviour-driven design framework for Lua.

   1  require 'luaspec'
   3  describe["Account, withdrawing funds"] = function()
   4      before = function()
   5          account = Account:new { balance = 100 }
   6          account:withdraw(10)
   7      end
   9      it["should remove the withdrawal amount from the balance"] = function()
  10          expect(account.balance).should_be(90)
  11      end
  12  end

It supports nested contexts, before and after functions, and has built-in support for mocking. More articles coming in the upcoming days describing all the functionality fully.

Null Smart Pointers Using Boost

Null Smart Pointers Using Boost

Managing memory is one of the pains that comes with developing in C++. Smart pointers such as std::auto_ptr help make things easier but they come with their own issues. My smart pointer implementation of choice is boost’s shared_ptr. A pattern I have found useful is:

   1  class Foo
   2  {
   3  public:
   4      typedef boost::shared_ptr<Foo> Ptr;
   5      static Foo::Ptr Null;
   6  public:
   7      // rest of declaration
   8  };

And then one can use them like:

   1  void f(Foo::Ptr foo)
   2  {
   3      if (foo == Foo::Null) 
   4      {
   5          // handle null case
   6      }
   7  }