Goes without saying: Crash safety

CINEMA 4D is known for its stability. While other 3D packages sometimes tend to randomly crash on you several times a day, CINEMA 4D runs stable and does not crash very often.

When you develop plugins for CINEMA 4D, you want to add functionality without making the whole application instable.

Page 1 | Page 2 | Page 3 | Page 4

Null Pointer checks

One of the most common reasons for crashes are NULL pointers that are accessed without checking first.

Allocating objects

When you allocate an instance of a class, you should always check for NULL pointers! This little check does not cost you much time but effectively prevents crashes. The point is, you can’t just believe that something has been successfully allocated, you have to know it. If the computer is running out of memory, or if the memory is highly fragmented, and you’re allocating a huge amount of memory, allocation might fail.

BaseObject* CreatePlane(Real width, Real height)
{
  BaseObject* op = BaseObject::Alloc(Oplane);
  BaseContainer* bc = op->GetDataInstance();
  bc->SetReal(PRIM_PLANE_WIDTH, width);
  bc->SetReal(PRIM_PLANE_HEIGHT, height);
  return op;
}

// ... later ...

BaseDocument* doc = GetActiveDocument();
BaseObject* plane = CreatePlane(RCO 200.0, RCO 300.0);

plane->SetName("My new plane");
doc->InsertObject(plane, NULL, NULL);

This code might work fine, but it might also just crash on some machines. Can you see how many potential crashes we have in this code? If you think “4”, you are right. There are four locations that could cause a crash.

BaseObject* CreatePlane(Real width, Real height)
{
  BaseObject* op = BaseObject::Alloc(Oplane);
  BaseContainer* bc = op->GetDataInstance();  // Access a member function of "op" without knowing if "op" has been allocated!
  bc->SetReal(PRIM_PLANE_WIDTH, width);       // Access a member function of "bc" without knowing if "bc" is valid!
  bc->SetReal(PRIM_PLANE_HEIGHT, height);
  return op;
}

// ... later ...

BaseDocument* doc = GetActiveDocument();
BaseObject* plane = CreatePlane(RCO 200.0, RCO 300.0);

plane->SetName("My new plane");               // Access a member function of "plane" without knowing if "plane" has been allocated!
doc->InsertObject(plane, NULL, NULL);         // Access a member function of "doc" without knowing if "doc" is valid

Even if it might seem unlikely that one of these situations might occur, it is possible. Adding some extra checks won’t hurt anybody, won’t decrease performance and effectively prevent your plugin from crashing:

BaseObject* CreatePlane(Real width, Real height)
{
  BaseObject* op = BaseObject::Alloc(Oplane);
  if (!op) return NULL;                        // Cancel if "op" has not been allocated

  BaseContainer* bc = op->GetDataInstance();
  if (!bc)                                     // Check if "bc" has been successfully retrieved
  {                                              // if not...
    BaseObject::Free(op);                        // ...free the already allocated "op"
    return NULL;                                 // ...and cancel
  }

  bc->SetReal(PRIM_PLANE_WIDTH, width);
  bc->SetReal(PRIM_PLANE_HEIGHT, height);

  return op;
}

// ... later ...

BaseDocument* doc = GetActiveDocument();
if (!doc) return;      // If there's no document at all, cancel (from whatever function we're in)

BaseObject* plane = CreatePlane(RCO 200.0, RCO 300.0);
if (!plane) return;    // If no plane has been created, cancel

plane->SetName("My new plane");
doc->InsertObject(plane, NULL, NULL);

VoilĂ , the code is now crash safe.

Allocating memory

Of course, Null Pointer checks should always be performed. Not only when allocating C4D objects, but generally always when memory is allocated for any purpose.

Real* myRealArray = GeAllocType(Real, 4096);
if (!myRealArray) return NULL;  // Check for NULL, in case the allocation was not successful
Avatar

Frank Willeke

worked with computers since more than 20 years | got hooked on computer graphics back on the AMIGA | started programming at the age of 13 | relesed some successful plugins for cinema 4d | started working for maxon computer gmbh in 2009 | now contributing to cinema 4d as a senior developer making electronic music since 1993 | playing the electric guitar since 1995 age of 14 | first live gigs in 1997 | playing the bass guitar 2005 | playing keyboards and synths since 2012 experimenting with photography since 2003