Anyone who’s ever needed to write cross-platform code in C or C++ knows that TRWTF is endianness. Your options are either to use a lot of platform specific preprocessor macros, or to coerce all of your data into your own specific format, for portability.

Adam H’s company took the latter approach, implementing a ByteWriter class. It was relatively easy to use, with code that looked something like this:

    byte* tempData = new byte[128];
    ByteWriter* writer = ByteWriter::Instance();
    writer->Initialize(tempData);
    writer->PutInt32(someIntValue);
    writer->PutInt32(someOtherIntValue);
    writer->PutByte(someByteArray);

At this point, tempData will hold your integers with the correct endianness, regardless of platform. But gee, that call to ByteWriter::Instance sure looks odd. Is that some kind of factory method? If so, that call to Initialize is weird. Let’s go to the implementation of the class…

    class ByteWriter
    {
    private:
        int _index;
        byte* _data;
        static ByteWriter *_instance = 0;
        ByteWriter() {}
    public:
        void Initialize(byte* data)
        {
            _index = 0;
            _data = data;
        }

        void PutInt32(int32_t w)
        {
            PutInt16((int32_t)(w & 0x0000FFFF));
            PutInt16((int32_t)((w & 0xFFFF0000) >> 16));
        }

        void PutInt16(int16_t w)
        {
            PutByte((byte)(w & 0x00FF));
            PutByte((byte)((w & 0xFF00) >> 8));
        }

        void PutByte(byte b)
        {
            _data[_index] = b;
            _index++;
        }

        static ByteWriter *Instance()
        {
            if (!_instance)
                _instance = new ByteWriter();
            return _instance;
        }
    }

And this is what drew Adam into this code in the first place- it was breaking any time it was touched by multiple threads, and of course it was. This is a classic example of the “Unnecessary Singleton” design pattern, commonly implemented by people who have skimmed the “Gang of Four” book, and needed to prove they knew what a design pattern was during an interview.

Unfortunately for Adam, this bit code highlights the problem, but:

This isn’t the source verbatim, as TRWTF here is hard to nail down to one snippet, but it should be clear with a few pieces. (It also means that I may have messed up C++ syntax)

It’s going to be much more complicated for him to actually fix.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!