我想在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)
。
这是正确的还是我缺少什么?我无法显示原始代码,但遇到了麻烦:
b->pages_len
。根据要求,提供一个最小的可复制示例:
/* 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%lu\n", my_book->pages_len[2]);
free (my_book->pages_len);
free (my_book);
}
我从内存泄漏检测器得到的是free(my_book)
给出了Memory corruption (written out of bounds?)
错误。解决此错误的一件事是更改了pages_count
和pages_len
的顺序,但我不知道为什么。
我刚刚输入了上面的示例,因此,如果有任何错别字或语法错误,请告诉我。谢谢。
答案 0 :(得分:0)
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
的类型,而应该继续在任何地方调用它struct book
,因为通常最好记住要使用的对象类型。但是,如果必须,您仍然可以在之后执行typedef struct book book;
。如上所述,我不推荐typedef struct book *book;
。
在C中永远不需要铸造malloc
的结果。大概包含了它是因为您收到关于malloc
返回类型的警告,但是正确的解决方法是包括标准标头{ {1}}。确实,这正是人们通常建议您不强制转换<stdlib.h>
的结果的原因,因为它可以使表示真实错误的警告静音。有关该主题的更多信息,请参见Do I cast the result of malloc?。
您还需要malloc
中的<stdio.h>
。
此外,test.c
应该返回一个值(但这不是导致崩溃的原因,因为您从未使用过它)。
毫不奇怪,重新排列结构成员使该错误似乎消失了。可能发生的事情是这样的。在典型的64位系统上,create_book
和指针均为8个字节。因此,当结构的大小实际上为16时,您已经为结构分配了8个字节。但是实际上您只写了size_t
成员。因此,如果pages_len
是该结构的第一个成员,而您从未写过pages_len
成员,那么您只在分配的8个字节内进行写操作,就不会出错。当然,代码仍然是坏的,一旦您添加了使用pages_count
成员的任何代码,或者添加或重新排列了结构的任何成员,该错误就会再次出现。
但是,总的来说,用C语言编程时盲目更改直到错误消失是一个非常糟糕的主意。您可能很容易做一些仅掩盖错误并难以发现的事情。真正了解正在发生的事情是无可替代的。