c - 如何在 C 中声明结构以避免结构损坏?

标签 c struct padding packing

我有类似的问题,如 this question我的问题得到了类似于 this answer 的解决但我不明白是什么导致了这个问题。 我有三个结构File , LineBufferapp.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;

Makefile如下:

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

有一个全局指针 Buffer结构:extern Buffer *bufferproto.h 中声明并在 global.c 中定义和*buffer动态分配在 io.cio.c中有几个函数与 *buffer 一起使用。我搬家了show_buffer() io.c的功能到另一个模块,如 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]);
        }

    }
}

我还删除了size File的成员结构。然后show_buffer()winio.c不再工作了。我发现show_buffer()正在处理损坏的 buffer->first指针。我重新编译了每个模块,但没有用。

当我添加 size 时问题就解决了File的成员再次结构。我还发现如果我移动 show_buffer()返回io.c ,问题就解决了。我怀疑结构填充可能会导致问题。

我的问题是导致问题的原因以及如何避免它。

分辨率

预编译 header 导致问题,因为它没有被重新编译。

最佳答案

结构定义是编译时数据。编译源文件后,生成的二进制组件将采用的 struct 布局是固定的。如果您无法确保系统中与给定 struct 类型一起使用的所有组件都具有相同的该类型布局理念(如下所述),那么很容易导致数据损坏。您很幸运,在您的案例中,腐败很容易识别。

您的struct定义应该(仅)出现在头文件中,并且依赖它的每个源文件都应该#include该头文件。如果您通过添加或删除成员、更改成员的类型或重新排序成员来修改struct的结构,则必须重新编译所有依赖 header 的源文件。 (任何半途而废的构建系统都将帮助您轻松实现这一目标。)

您可以通过使用指向 struct 类型的指针而不是使用 struct 本身来在某种程度上使自己免受此类问题的影响,但这仅在您需要取消引用指针。

关于c - 如何在 C 中声明结构以避免结构损坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28571641/

相关文章:

c - 字符数组初始化产生段错误

在编写 Python C 扩展时创建 Python 列表

c - 如何让 "rand()"生成实际的随机数?

c - 打印结构字段多次只打印最后一个元素 - C

c++ - 结构默认构造函数 : will it initialize my members with default vaues i. e。 'zeros'

html - 向单个 div 添加填充

c - 使用我自己的结构在套接字编程中填充 UDP 负载?

C++ 深度复制链表

html - 如何删除链接 <a> 和它位于 <li> 中的列表项之间的所有填充?或者...点击 <li> 打开里面的链接?

jquery - 仅当鼠标非常缓慢地离开 div 时,子菜单上的滑动效果才起作用