Weird enum values in shared modules – a Codegear Rad Studio new default compiler setting

I have worked in Borland / CodeGear / Embarcadero (whatever you call it now) C++ and Delphi since Delphi v1 (16bit) / Borland C++ Builder v3 were first released. Over the years I would periodically be tasked with upgrading products from one version of Borland Compilers to another. Today was a very awkward moment as I reflect on a very interesting problem that I came across in the C++ enum type as used some products.

In this particular suite of products we have a number of DLL (bpl) libraries where shared code resides. One of these base package libraries actually contained the definition of a group of enums. These projects were created pre – rad studio 2007. Early this year I was asked to proto-type something as an active-x project and thus a few new projects were created “Brand new” in Rad Studio 2007 (exclusively in C++ Builder persona). The header file containing the enum declarations was added to an OLD bpl project while the new projects created and passed around variables of the new enum type(s). This is where the problems began.

Suddenly while debugging through code and stepping from one project library to another the enum value held in the variables (but passed from one layer to another) changed from say a value of 4 to some crazy huge number like 10439848! Much time was wasted and many work arounds attempted but the problem bothered me and gave great concern. Recompiling everything and moving stuff around etc.. does NOT solve this! Of course you could change the enum to a bunch of static int’s and pass int’s around everywhere, that would work, but is much less elegant and much less readable and very much like a “java” style solution. I’ll cut to the point.

I introduce the following witness:

C++ Compiler General Compilation

Integer-sized enums (-b) Allocates a whole word (a four-byte int for 32bit programs) for enumeration types (variables of type enum).
When this option is off (-b-), the compiler allocates the smallest integer that can hold the enumeration values: the compiler allocates an unsigned or signed char if the values of the enumeration are within the range of 0 to 255 (minimum) or -128 to 127 (maximum), or an unsigned or signed short if the values of the enumeration are within the following ranges:
0..65535 or -32768..32767.
The compiler allocates a four-byte int (32-bit) to represent the enumeration values if any value is out of these ranges.
(Default = true)

I am not sure when this flag was introduced (I see that it was definitely there in C++ Builder 6) but the real problem lies in RAD Studio’s little comment about the Default = true! In C++ Builder 6 if you create a new project it will default to turn OFF treat enums as int…. so for a small enum with say 5 entries you store that variable in 1 byte. But in Rad Studio 2007 if you create a new project then it will default to turn ON treat enums as int. So the old BPL’s compile the enum with 1 byte while the new projects default to compile the enum with 4 bytes. So all related DLL’s, BPL’s and EXE’s and OCX’s that share your enums MUST have the same setting for treat enums as int or you will stomp on memory!

I am not sure who decided to change this default at Codegear and in what version of the compiler it started, but I for-see a lot of problems related to this one. I hope I used all the right words to place your google search here and spare having you come to the brink of insanity to figure out why, when debugging your code the value of your enum randomly changes its value! This has also caused access violations and many other unpredictable behaviour as your memory for the enum gets crushed. Hope this is helpful.


Comments are closed.