Showing posts with label C++. Show all posts
Showing posts with label C++. Show all posts

Wednesday, 15 February 2012

Static code analysis

One simple way of improving your code is passing it through some of static code analysis tools and fix reported errors and warnings. Such tools will usually point out lines in code that could possibly cause issues with buffer overruns, uninitialized memory, null pointer dereferences, memory and resource leaks, exception safety...or lines that contain code which style could be improved.

If you are using Visual Studio 2010, you can use its static code analysis: open Project Properties -> Configuartion Properties -> Code Analysis. Select desired build configuration and platform and tick Enable Code Analysis for C/C++ on Build. Output window will show code analysis report (search for Running Code Analysis for C/C++... lines).

I want to show here how it looks in the practice. Let's say we have some smelly code:

C.h:

#ifndef _C_H_
#define _C_H_

class C
{
   // unitialized member
   int m_n;
public:
   C()
   {  
      // unused variable
      int j;
   }

   void Init(char ch)
   {
      // C-style pointer cast
      m_n = (int)ch;
   }
};
#endif // _C_H_


main.cpp:

#include "C.h"

// unused function
int foo()
{
   int n;
   return 0;
}

int main()
{
   // unused variable
   int n1; 

   // dereferencing unitialized pointer
   int* pInt1;
   *pInt1 = 1;

   // dereferencing NULL pointer
   int* pInt2 = 0;
   *pInt2 = 2;

   // memory leak - no delete
   int* pInt3 = new int(2);

   // scope of n2 is unecessarily main()
   int n2 = 0;

   {
      char ch = 2;
      n2 = (int)ch;
   }

   int arr[2];
   arr[2] = 3;

   return 0;
}


I played recently with Cppcheck and this is what it reports for the code above:

Cppcheck-report

Visual Studio prints code analysis messages in the Output window and for the code above it contains the following:

1>------ Build started: Project: CppcheckTest, Configuration: Debug Win32 ------
1>Build started 15/02/2012 19:49:12.
1>InitializeBuildStatus:
1> Touching "Debug\CppcheckTest.unsuccessfulbuild".
1>ClCompile:
1> main.cpp
1>c:\...\cppchecktest\c.h(12): warning C4101: 'j' : unreferenced local variable
1>c:\...\cppchecktest\main.cpp(6): warning C4101: 'n' : unreferenced local variable
1>c:\...\cppchecktest\main.cpp(13): warning C4101: 'n1' : unreferenced local variable
1>c:\...\cppchecktest\main.cpp(35): warning C6201: Index '2' is out of valid index range '0' to '1' for possibly stack allocated buffer 'arr'
1>c:\...\cppchecktest\main.cpp(17): warning C6001: Using uninitialized memory 'pInt1': Lines: 13, 16, 17
1>c:\...\cppchecktest\main.cpp(21): warning C6011: Dereferencing NULL pointer 'pInt2': Lines: 13, 16, 17, 20, 21
1>c:\...\cppchecktest\main.cpp(35): warning C6386: Buffer overrun: accessing 'arr', the writable size is '8' bytes, but '12' bytes might be written: Lines: 13, 16, 17, 20, 21, 24, 27, 30, 31, 34, 35
1>c:\...\cppchecktest\main.cpp(17): warning C4700: uninitialized local variable 'pInt1' used
1>ManifestResourceCompile:
1> All outputs are up-to-date.
1>Manifest:
1> All outputs are up-to-date.
1>LinkEmbedManifest:
1> All outputs are up-to-date.
1> CppcheckTest.vcxproj -> C:\...\CppcheckTest\Debug\CppcheckTest.exe
1>FinalizeBuildStatus:
1> Deleting file "Debug\CppcheckTest.unsuccessfulbuild".
1> Touching "Debug\CppcheckTest.lastbuildstate".
1>
1>Build succeeded.
1>
1>Time Elapsed 00:00:04.38
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========


Links and References:
Analyzing Application Quality by Using Code Analysis Tools (MSDN)
How to: Enable and Disable Automatic Code Analysis for C/C++ (MSDN)
Cppcheck

Tuesday, 25 October 2011

Finite State Machine in C

Finite State Machine is a way of modelling behaviour of some entity that can have a (finite) set of states. Depending on the received event, entity performs some action and changes its state (or remains in the current one).

Let's say we want to model a behaviour of some simple car. I call it "simple" as it has only ignition switch, accelerator and brake. Driver can turn it on, then accelerate, brake and, at the end of the journey, turn it off. If not careful, driver can break the car - if tries to turn it on (again) while driving. Driver's actions are events - inputs of our model. Car can be turned off, idling, moving or broken - and this is a set of our car's states. So, car is in some state, it reacts on driver's command (event), performs some action and goes into the next state.

We have a finite set of states and events and can draw a diagram which precisely define state transitions (state transition diagram):


FSM_CarExample_1

Now, how to implement this model and show how this state machine changes states after receiving events?

Each state can be represented as unique number - its code, or ID. The similar thing is with events. As we have finite number of both states and events, we can use enum type to represent them: one variable will be of enum STATE type and contain the ID of the current state and another variable will be of type enum EVENT and will contain the most recent event this system received. Initially, our car is turned off so the state variable will be set to STATE_TURNED_OFF. After this simple initialization we just need to wait for events and handle them in accordance to the given transition diagram. Events can be obtained from a keyboard or some other source and they are usually kept in a queue as sometimes a new event can be received before processing of the previous one is finished. In this example, in order to keep things simple, I'm gonna assume that processing is fast enough and will just create a predefined set of events and put them in an array.

As we have repetitive action - receiving and handling events - we'll put it in a loop. If our events source is keyboard and we don't know how many events will user issue, we can use while-loop and CTRL-C as a loop termination command. In this example, we have an array of events which is of predefined (known in advance) size so we can use for-loop. Inside this loop, we need to place event processing code for each event, received in each state. This means we will have switch-statement inside another switch-statement. So, here's the code:

main.c:



Output:

Whoooa! I'm turned on!
Yipee! I'm accelerating!
Whoops! Was I too fast?
That was probably enough...

Having a switch inside a switch looks a bit complex and difficult to maintain. If we add a new state, we need to add a new case-branch for each event. In the code above it would mean we need to make changes at 4 different places in the code! Not good!

A solution for this is a state transition table. It is basically a table in which each state has its column and each event has its row. Table elements are pairs action/next-state - let's put them in some structure called TRANSITION. If transition table is called trans_tbl its element, trans_tbl[evt][state] is of type TRANSITION and action is a function called during transition and next-state is the state our model goes into for the current event. Code tells this better:

main.c:


Output is the same:

Whoooa! I'm turned on!
Yipee! I'm accelerating!
Whoops! Was I too fast?
That was probably enough...

The code has shrunk and become easier to understand and maintain: if we want to add a new event or a state, we just need to change transition table (trans_tbl) - we don't need to touch the code in a loop!

My article "Finite State Machine in C++" shows how to use OOP and State design pattern in order to implement FSM described here.

Links and references:
Finite-state machine (Wikipedia)
UML Tutorial: Finite State Machines