Archive

Archive for the ‘C++’ Category

Sloppy Coding

March 18, 2017 1 comment

I won’t disclose which open source code base contains this C++ code because I don’t want to injure any fragile egos. However, I’ll give you a hint. This sloppy code runs a $20 billion, bleeding edge, financial system. The stewards of this code base think they walk on water.

Categories: C++

Subtle And Quirky, But Still Lovable

December 3, 2016 Leave a comment

I’m a long time C++ programmer who’s going to expose something embarrassing about myself. As a starting point, please take a look at the code below:

stdmap

The first std::cout statement prints out the letter A and the second one prints out B. Here comes the embarrassing part… I erroneously thought that both the map::insert() and map::operator[] functions expressed the same semantics:

If the map object already contains an entry for the key being supplied by the user in the function call, the value supplied by the user will not be copied into the map.

Applied to the specific example above, before running the program I thought both std::cout statements would print the letter A.

Of course, as any experienced C++ programmer knows (or, in my case, should know), this behavior is only true for the map::insert() function. The map::operator[] function combined with the assignment operator will always copy the value into the map – regardless of whether or not an entry for the key is already present in the map. It makes sense that the two functions behave differently because sometimes you want an unconditional copy and sometimes you don’t.

The reason I wrote this post is because I very recently got burned by my incorrect assumption. To make a long story short, there was a bug in my large program that eventually was traced, with the help of the simple code example above, to the bad line of code that I wrote using map::operator[]. A simple change to map::insert() fixed the bug. It was critical to the application that an existing value in the map not be overwritten.

One of the dings against C++ is that it contains a lot of subtle, quirky semantics that are difficult for mere humans to remember. Despite agreeing with this, I still love the ole language that keeps on chugging forward like the little train that could (direct mapping to the hardware and zero overhead abstraction), despite the chagrin of many in the software industry:

I consider C++ the most significant technical hazard to the survival of your project and do so without apologies – Alistair Cockburn

Categories: C++ Tags:

The “unsigned” Conundrum

October 16, 2016 25 comments

A few weeks ago, CppCon16 conference organizer Jon Kalb gave a great little lightning talk titled “unsigned: A Guideline For Better Code“. Right up front, he asked the audience what they thought this code would print out to the standard console:

mixed-mode-math

Even though -1 is obviously less 1, the program prints out “a is not less than b“. WTF?

The reason for the apparently erroneous result is due to the convoluted type conversion rules inherited from C regarding unsigned/signed types.

Before evaluating the (a < b) expression, the rules dictate that the signed int object, a, gets implicitly converted to an unsigned int type. For an 8 bit CPU, the figure below shows how the bit pattern 0xFF is interpreted differently by C/C++ compilers depending upon how it is declared:

 

eightbits

 

Thus, after the implicit type conversion of a from -1 to 255, the comparison expression becomes (255 < 1) –  which produces the “a is not less than b” output.

Since it’s unreasonable to expect most C++ programmers to remember the entire arcane rule set for implicit conversions/promotions, what heuristic should programmers use to prevent nasty unsigned surprises like Mr. Kalb’s example?  Here is his list of initial candidates:

 

unsignedguidlines

If you’re trolling this post and you’re a C++ hater, then the first guideline is undoubtedly your choice :). If you’re a C++ programmer, the second two are pretty much impractical – especially since unsigned (in the form of size_t) is used liberally throughout the C++ standard library. (By the way, I once heard Bjarne Stroustrup say in a video talk that requiring size_t to be unsigned was a mistake). The third and fourth guidelines are reasonable suggestions; and those are the ones I use in writing my own code and reviewing the code of others.

At the end of his interesting talk, Mr. Kalb presented his own guideline:

kalbguideline

I think Jon’s guideline is a nice, thoughtful addition to the last two guidelines on the previous chart. I would like to say that “Don’t use “unsigned” for quantities” subsumes those two, but I’m not sure it does. What do you think?

Categories: C++ Tags: , ,

Plugging Those Leaks

October 6, 2016 2 comments

It’s been 5 years since modern C++ arrived on the scene in the form of the C++11 standard. Prior to the arrival, C++ was notorious for memory leaks and segmentation faults due to the lack of standardized smart pointers (although third party library and home grown smart pointers have existed for decades). Dangerous, naked news and deletes could be found sprinkled across large code bases everywhere – hidden bombs waiting to explode at any moment during runtime.

I don’t know how many over-confident C++ programmers are still using the old new/delete pattern in new code bases, but if your team is one of them please consider hoisting this terrific poster on the walls of your office:

leakfree

ISO WG-21 C++ committee convener Herb Sutter, a tireless and passionate C++ advocate for decades, presented this poster in his CppCon 2016 talk “Leak Freedom In C++: By Default“. Go watch it now.

Categories: C++ Tags: , ,

Move In, Move Out

August 14, 2016 2 comments

In many application domains, the Producer-Queue-Consumer pattern is used to transport data from input to output within a multi-threaded program:

producerconsumer

The ProducerThread creates Messages in accordance with the application’s requirements and pushes pointers to them into a lock-protected queue. The ConsumerThread, running asynchronous to the ProducerThread, pops sequences of Message pointers from the queue and processes them accordingly. The ConsumerThread may be notified by the ProducerThread when one or more Messages are available for processing or it can periodically poll the queue.

Instead of passing Message pointers, Message copies can be passed between the threads. However, copying the content can be expensive for large messages.

When using pointers to pass messages between threads, the memory to hold the data content must come from somewhere. One way to provide this memory is to use a Message buffer pool allocated on startup.

MsgBufferPool

Another, simpler way that avoids the complexity of managing a Message buffer pool, is to manually “new” up the memory in the ProducerThread and then manually “delete” memory in the ConsumerThread.

newdelete

Since the introduction of smart pointers in C++11, a third way of communicating messages between threads is to “movestd::unique_ptrs into and out of the InterThreadQueue:

moveinmoveout

The advantage of using smart pointers is that no “deletes” need to be manually written in the ConsumerThread code.

The following code shows the implementation and usage of a simple InterThreadQueue that moves std::unique_ptrs into and out of a lock protected std::deque.

InterthreadQueueImpl

InterThreadQueueUsage

#include "catch.hpp"
#include <memory>
#include <deque>
#include <mutex>
#include <vector>
#include <stdexcept>

template<typename Msg>
class InterThreadQueue {
public:
  InterThreadQueue(int32_t capacity) :
    _capacity(capacity) {}

  void push(std::unique_ptr<Msg> msg) {
    std::lock_guard<std::mutex> lg(_mtx);
    if(_queue.size() not_eq _capacity) {
      _queue.push_back(std::move(msg));
    }
    else {
      throw std::runtime_error{"Capacity Exceeded"};
    }
  }

  std::vector<std::unique_ptr<Msg>> pop() {
    std::vector<std::unique_ptr<Msg>> msgs{};
    std::lock_guard<std::mutex> lg(_mtx);
    while(not _queue.empty()) {
      msgs.emplace_back(std::move(_queue.front()));
      _queue.pop_front();
    }
    return msgs; //Move the vector to the caller
  }

private:
  mutable std::mutex _mtx{};
  const std::size_t _capacity;
  std::deque<std::unique_ptr<Msg>> _queue;
};

TEST_CASE( "InterThreadQueue" ) {
  //Create our object under test
  InterThreadQueue<int32_t> itq{2};

  //Note: my compiler version doesn't have std::make_unique<T>()
  std::unique_ptr<int32_t> dataIn{new int32_t{5}};
  itq.push(std::move(dataIn));
  dataIn = std::unique_ptr<int32_t>{new int32_t{10}};
  itq.push(std::move(dataIn));

  dataIn = std::unique_ptr<int32_t>{new int32_t{15}};
  //Queue capacity is only 2
  REQUIRE_THROWS(itq.push(std::move(dataIn)));

  auto dataOut = itq.pop();
  REQUIRE(2 == dataOut.size());
  REQUIRE(5 == *dataOut[0]);
  REQUIRE(10 == *dataOut[1]);

  REQUIRE(0 == itq.pop().size());
}
Categories: C++ Tags: ,

Generating NaNs


Nanonano
While converting serialized double precision floating point numbers received in a datagram over a UDP socket into a native C++ double type, I kept getting NaN values (Not a Number) whenever I used the deserialized version of the number in a numeric computation. Of course, the problem turned out to be the well-known Endian” issue where one machine represents numbers internally in Big Endian format and the other uses Little Endian format.

Endians

One way of creating a NaN is by taking the square root of a negative number. Another way is to jumble up the bytes in a float or double such that an illegal bit pattern is produced. Uncompensated Endian mismatches between machines can easily produce illegal bit patterns that create NaNs. Note that NaNs are only an issue in the floating point types because every conceivable bit pattern stored in an integral type is always legal.

To prove just how easy it is to produce a NaN by jumbling up the bytes in a double, I wrote this little program that I’d like to share:

NanGen

Here is a fragment of the output from a typical program run:

NanOut

I was a little surprised at the low number of iterations it typically takes to produce a NaN, but that’s a good thing. If it takes millions of iterations, it may be hard to trace a bug back to a NaN problem.

For those who would try this program out, here is a copy-paste version of the code:

#include <cstdint>
#include <iostream>
#include <random>
#include <cmath>

int main() {
    //Determine the number of bytes in a double
	const int32_t numBytesInDouble{sizeof(double)};

	//Create a fixed-size buffer that holds the number of bytes
	//in a double
	int8_t buffer[numBytesInDouble];

    //Setup a random number generator to produce
    //a uniformly distributed int8_t value
    std::random_device rd{};
    std::mt19937 gen{rd()};
    std::uniform_int_distribution<int8_t> dis{-128, 127};

    //interpret the buffer as a double*
    const double* dp{reinterpret_cast<double*>(buffer)};
    int32_t count{-1};
    do{
      //fill our buffer with random valued bytes
      for(int32_t i=0; i<numBytesInDouble; ++i) {
        buffer[i] = dis(gen);
      }

      std::cout << *dp << "\n";
      ++count;
    }while(not std::isnan(*dp));

    std::cout << "count = " << count << "\n";
}
Categories: C++ Tags: ,

M Of N Fault Detection


Let’s say that, for safety reasons, you need to monitor the voltage (or some other dynamically changing physical attribute) of a safety-critical piece of equipment and either shut it down automatically and/or notify someone in the event of a “fault“.

FaultDetection

The figure below drills into the next level of detail of the Fault Detector. First, the analog input signal is digitized every ΔT seconds and then the samples are processed by an “M of N Detector”.

Fault Detector

The logic implemented in the Detector is as follows:

MofNLogic

Instead of “crying wolf” and declaring a fault each time the threshold is crossed (M == N == 1), the detector, by providing the user with the ability to choose the values of M and N, provides the capability to smooth out spurious threshold crossings.

The next figure shows an example input sequence and the detector output for two configurations: (M == N == 4) and (M == 2, N == 4).

FDExamples

Finally, here’s a c++ implementation of an M of N Detector:

#ifndef MOFNDETECTOR_H_
#define MOFNDETECTOR_H_

#include <cstdint>
#include <deque>

class MofNDetector {
public:
  MofNDetector(double threshold, int32_t M, int32_t N) :
    _threshold(threshold), _M(M), _N(N) {
    reset();
  }

  bool detectFault(double sample) {

    if (sample > _threshold)
      ++_numCrossings;

    //Add our newest sample to the history
    if(sample > _threshold)
      _lastNSamples.push_back(true);
    else
      _lastNSamples.push_back(false);

    //Do we have enough history yet?
    if(static_cast<int32_t>(_lastNSamples.size()) < _N) {
      return false;
    }

    bool retVal{};
    if(_numCrossings >= _M)
      retVal = true;

    //Get rid of the oldest sample
    //to make room for the next one
    if(_lastNSamples.front() == true)
      --_numCrossings;

    _lastNSamples.pop_front();

    return retVal;
  }

  void reset() {
    _lastNSamples.clear();
    _numCrossings =0;
  }

private:
  int32_t _numCrossings;
  double _threshold;
  int32_t _M;
  int32_t _N;
  std::deque<bool> _lastNSamples{};

};

#endif /* MOFNDETECTOR_H_ */
Categories: C++, technical Tags: ,
%d bloggers like this: