DEV Community

Georg Nikodym
Georg Nikodym

Posted on

1 2

C Functions Calling Other Functions With Side Effects

#c

Recently, I've been working on a project and seeing a lot of this pattern:

void func(void) {
  retVal = thing1WithSideEffects();
  if (0 == retVal) thing2WithSideEffects();
  if (0 == retVal) thing3WithSideEffects()
  if (0 == retVal) thing4WithSideEffects();

  if (0 != retVal) return retVal;

  // do other func()y stuff
}

By side effect, I mean a change in the state of the system. The side effect might be a new open file, a memory allocation, the establishment of a TCP connection, whatever.

First, the style. The tests of retVal are actually checking things from the line above so reading this code is weird.
While I'm nitpicking, I hate "Yoda Conditions".

Way more importantly, however, is that if any one of the calls fails, the system is left in an indeterminate state. If retVal has a value by line 7, we have no idea what the failure was and we cannot call any cleanup functions to undo any of the side effects.

The calling program/function, detecting an error with func() cannot call func() again unless it knows how to clean things up.

Yes, getting this right is hard since you end up with something like this:

void func(void)
{
  if (retVal = thing1WithSideEffects()) return retVal;
  if (retVal = thing2WithSideEffects()) {
    undoThing1();
    return retVal;
  }
  if (retVal = thing3WithSideEffects()) {
    undoThing2();
    undoThing1();
    return retVal;
  }
  // ad nauseum -- you get the idea
}

A little bit gross (clean-up is beyond the scope of what I'm trying to get across) and hard to get-right/test.

I totally understand not wanting to do all this when you’re just under deadline, trying to get stuff working and out the door but the code we write tends to outlive us.

But we can and should do better.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (1)

Collapse
 
ac000 profile image
Andrew Clayton

Linux Kernel coding style has you covered, slide 11 onwards...

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay