c-通过构造函数为结构指针成员分配空间



我想在C.中使用类似对象的结构

假设我有以下内容:

typedef struct {
/* ... */
size_t *pages_len;
} book;

我使用以下方法来构建它:

int book_init(/* some args... */, book * b) {
/* do some validation */
/* compute the number of pages n_pages */
b->pages_len = (size_t*) calloc(n_pages, sizeof(size_t));
/* compute pages_len based on some args */
return 0;
}

然后我构造了一个这样的对象:

book *my_book = (book*)malloc(sizeof(my_book));
if (book_init(/* some args */, my_book) == 0) {
/* do something */
}

我破坏了我的对象,比如:book_destroy(book *b),这里是free(b->pages_len)

这是正确的还是我遗漏了什么?我无法显示原始代码,但我遇到了问题:

  1. 在init方法之后访问b->pages_len
  2. 正在销毁对象。我的记忆力衰退了

根据要求,一个可重复的最小示例:

/* book.h */
#ifndef BOOK_HEADER_
#define BOOK_HEADER_
#include <ctype.h>
typedef struct
{
size_t pages_count;
size_t *pages_len;
} * book;
int book_create (book b);
#endif /* BOOK_HEADER_ */
/* book.c */
#include "book"
int
book_create (book b)
{
b->pages_len = calloc (3, sizeof (b->pages_len));
b->pages_len[2] = 20;
return 0;
}
/* test.c */
#include "book.h"
int main(int argc, char** argv) {
book my_book = (book)malloc (sizeof (book));
int r = book_create (my_book);
printf ("n%lun", my_book->pages_len[2]);
free (my_book->pages_len);
free (my_book);
}

我从内存泄漏检测器得到的是free(my_book)给出了Memory corruption (written out of bounds?)错误。修复这个错误的一件事是更改pages_countpages_len的顺序,但我不知道为什么。

我刚刚打了上面的例子,所以如果有任何拼写错误或句法错误,请告诉我。非常感谢。

book my_book = malloc(sizeof(book))错误。请注意,book的类型是指向结构的指针,但您希望为结构本身分配足够的空间。因此,就目前的代码而言,您将需要编写malloc(sizeof(*my_book))

然而,使用typedef来定义指针的名称通常是不好的风格;这会导致混乱,并且您会发现结构类型没有名称非常尴尬。写这篇文章的更好方法是作为

struct book
{
size_t pages_count;
size_t *pages_len;
};
struct book *my_book = malloc(sizeof(*my_book));

在这种情况下,malloc(sizeof(struct book))也可以工作,但如果您更改my_book的类型,则会损坏。

经常有人建议你不要对struct进行typedef,而是在任何地方都继续称它为struct book,因为记住你正在处理的对象类型通常是很好的。但如果必须的话,你仍然可以在之后做typedef struct book book;。如前所述,我不会推荐typedef struct book *book;

在C中不应该强制转换malloc的结果。您可能包含了它,因为您收到了关于malloc返回类型的警告,但正确的解决方案是包含标准标头<stdlib.h>。事实上,这正是人们通常建议您执行而不是投射malloc结果的原因,因为它可以使指示真正错误的警告静音。请参阅我是否投射malloc的结果?了解有关此主题的更多信息。

您还需要test.c中的<stdio.h>

此外,create_book应该返回一个值(但这不是崩溃的原因,因为您从未使用过它(。

毫不奇怪,重新排列结构成员会使错误看起来消失。可能发生的事情是这样的。在典型的64位系统上,size_t和指针各为8个字节。所以您为结构分配了8个字节,而它的大小实际上是16。但你实际上只是写信给pages_len成员。因此,如果pages_len是结构的第一个成员,并且您从未向pages_count成员写入,那么您只在分配的8个字节内写入,不会出现任何问题。当然,代码仍然是坏的,一旦添加了任何使用pages_count成员的代码,或者添加或重新排列了结构的任何成员,错误就会回来。

但总的来说,在C中编程时,盲目地更改内容直到错误消失是一个非常糟糕的主意。你可能很容易做一些只屏蔽错误并使其更难找到的事情。真正了解正在发生的事情是无可替代的。

最新更新