dMaggot meets Alignment

I've been giving lots of support on OpenGL programming lately because of a project my classmates had to turn in. One of them wanted to load a texture file into the code, and even though I've done that before on another project of my own, I have to admit I didn't use a very high level approach to the task, so I recommended her a function I saw once while reading the OpenGL Super Bible.

The task of implementing the function into her code seemed simple: the whole code of the book is available at it's web site, so after downloading it, I checked if the function required any special library, and it didn't, so all she needed to do was copying and pasting the function implementation. But of course, it didn't work as expected (if it had, then I wouldn't be writing this). The code threw some errors, even when trying to load the same TGA file from the book's code. After adding some debugging printfs, I noticed the function wasn't actually failing at any point, yet after reading the bytes from the file, the read data was corrupted. Specifically, the code uses the following structure to store a TGA Header information:

typedef struct
{
GLbyte identsize;
GLbyte colorMapType;
GLbyte imageType;
unsigned short colorMapStart;
unsigned short colorMapLength;
unsigned char colorMapBits;
unsigned short xstart;
unsigned short ystart;
unsigned short width;
unsigned short height;
GLbyte bits;
GLbyte descriptor;
} TGAHEADER;

Taking into account the datatype sizes, (GLbyte: 1 byte, unsigned short: 2 bytes, unsigned char: 1 byte), that's an 18 bytes structure to store the header, as specified by the TGA file format. The statement that loaded the info into the header was

fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile);

which seemed OK to me at the beginning. Yet the result of the operation was always giving weird numbers. I first thought of corrupt data files, but it wasn't the case as I could successfully load those files in my image editor. I also thought that something could have failed while opening the file pointer, but there was no error on the fopen instruction, plus there were some data fields that were loaded fine. I then took a look at the program under the gdb debugger and after printing some of the file contents, I did an interesting finding: the size of the structure was not 18, but 20. By checking the memory locations of all the fields of the tgaHeader structure, colorMapStart was placed 2 bytes after imageType and xstart was placed 2 bytes after colorMapBits, even though both imageType and colorMapBits were just 1 byte long. The reason is obvious: the compiler did that for alignment purposes; yet I must confess I had never seen something like that before anywhere outside the books (:$ shame on me).

I then did the obvious fix: reading each member of the header structure one by one, and we finally had a working version of the TGA file loader. Yet, besides learning a lot more about TGA headers than what I ever wanted to know, I also learned two important things that day: never reading all contents from a file into a structure, and the importance of gdb for real life debugging.