Search code examples
cstructpaddingpacking

How to declare structures in C to avoid structure corruption?


I have a similar problem like this question and my problem was solved similar to this answer but I can't understand what caused this issue. I have three structures File, Line and Buffer declared in app.h.

typedef struct File {
    FILE *fs;
    char *path;
    size_t size;
} File;

typedef struct Line Line;
struct Line {
    char *text;
    size_t len;
    size_t line_no;
    Line *next;
    Line *prev;
};

typedef struct Buffer {
    int id;
    File file;
    Line *first;
    Line *last;
    Line *current;
    int x_pos;
    int y_pos;
    int visual_x;
    bool modified;
} Buffer;

The Makefile is as follow:

CC = gcc
CFLAGS = -Wall -Werror -g
LDFLAGS = 
LDLIBS = -lcurses
OBJECTS = app.o io.o global.o move.o winio.o utils.o

all: app

app: $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) $(LDLIBS) -o $@

%.o: %.c proto.h app.h
    $(CC) $(CFLAGS) -c $<

.PHONY: clean
clean:
    -rm app
    -rm *.o

There is a global pointer for Buffer structure: extern Buffer *buffer declared in proto.h and defined in global.c and *buffer is dynamically allocated in io.c. There are several functions in io.c that work with *buffer. I moved show_buffer() function of io.c to another module like winio.c

void show_buffer()
{
    size_t i = 0, j = 0;
    Line *it;

    for (it = buffer->first; it != NULL && i < (LINES - STATBAR_HEIGHT);
            it = it->next, i++) {
        for (j = 0; it->text[j] != '\0'; j++) {
            waddch(mainwin, it->text[j]);
        }

    }
}

and I also removed size member of File structure. Then show_buffer() in winio.c didn't work anymore. I found out that show_buffer() was working with corrupted buffer->first pointer. I recompiled every module but didn't work.

The problem solved when I added size member of File structure again. I also figured out that if I move show_buffer() back to io.c, the problem would be solved. I suspect structure padding might cause the problem.

My question is what caused the problem and how to avoid it.

Resolution

A precompiled header was causing problems because it was not being recompiled.


Solution

  • I answer my question in the hope that it will be useful for others. While I was investigating the cause of the problem, I stumbled upon a precompiled header file app.h.gch in the working directory. I suspect that in the previous versions of my Makefile, I had passed app.h to the compiler without being aware of it. Unfortunately there was no rule in the Makefile to remove precompiled headers. When I removed app.h.gch and recompiled the whole project, everything got back to normal.