结构中 p* 的潜在问题?

Potential issues with p* in structs?

过去几个月我一直在研究 C。为了学习这门语言,该项目是一个算术解析器 - 公式、变量等。

我最近决定继续进行垃圾收集,因为我有很多次调用此方法:

char* read_token(const Source* source, const Token* token) {
    int szWord = token->t_L + 1;        //  +1 for NULL terminator
    char* word = (char*)malloc(sizeof(char)*szWord);
    memset(word, '[=10=]', sizeof(char)*(szWord));
    char* p_T = source->p_Src + token->t_S;
    memcpy(word, p_T, token->t_L);

    return word;
}

...这意味着调用 free(...) 相当多。

Source 结构有两个缓冲区属性:

typedef struct source Source;
struct source {
    // ...
    char* p_Src;            // malloc'd source buffer
    int srcLen;
    Token* p_tokens;        // malloc'd Token buffer
    // ...
};

Token 结构具有 startlength 属性:

typedef struct token Token;
struct token {
    int t_S;                // buffer start index
    int t_L;                // token length
};

此外,由于可能有很多 sourceSource* 缓冲区是 malloc。 当缓冲区为 malloc 时,将提供结构的大小 (* numStructs)。但是如果给定的结构有一个可以在以后分配的缓冲区,例如 Token*,这会改变 Source 的大小吗?代码是否有覆盖先前分配的内存的危险?

出于某种原因,我认为用于结构的所有内存(包括任何缓冲区)都是以线性方式分配的。如果结构中的 Token* 缓冲区分配给 10 个标记,那么 space 就不会在 Source 结构中线性分配,对吗?

struct 中的指针成员是存储内存块地址的变量,正如您自己所说,指针和指针是 独立分配的 。因此,这些缓冲区可能位于其 'parent' struct 存储位置的旁边,也可能不在(很可能不会)。

如果需要,确保 struct 成员及其指向缓冲区的连续存储可以通过在对 [=13= 的一次调用中分配所有内容来实现] 函数。

这是可以做到的

  • 使用固定大小的缓冲区:不太方便,因为缓冲区大小的任何灵活性都丢失了。另请注意,声明此更新会相应地更新 sizeof(struct foo) 的值。
  • 使用 C99 的 灵活数组成员 或技巧在 C99 之前的 C 中启用该功能: .
  • 使用不推荐的 hacks 求助于指针算法,注意编译器的对齐策略。

结构中的指针是固定大小的,无论它指向什么,即使它未初始化也是如此。这样,sizeof(struct token) 就是一个固定长度。

当使用malloc时,内存是从堆中的某处获取的,我们不知道在哪里,也不应该关心。在原始结构附近的任何地方分配内存的可能性极小,即使是,那也是特定于实现的,您不能指望这种行为。

显然(?)您应该在指针所在的结构被销毁之前调用 free()

另请注意 C99 的 Variable Length Arrays(VLA)。

抱歉,我在 "Answer" 部分而不是 "Comments" 部分写这篇文章,因为我的 Whosebug 声誉还不够高。 我要评论的是你为什么不只使用这一行:

char word[ sizeof(char)*szWord ];

而不是

char* word = (char*)malloc(sizeof(char)*szWord); ?