Да, общая идея взлома верна, но, по крайней мере, когда я ее прочитал, вы не совсем правильно ее реализовали. Это вы правильно сделали:
f = malloc(num + sizeof(foo) + MAX_COMMENT_SIZE );
f->data = f + 1; // is this OK?
Но это не так:
f->comment = f + 1 + num;
Поскольку f
равно foo *
, f+1+num
вычисляется в терминах sizeof(foo)
- то есть это эквивалентно высказыванию f[1+num]
- он (пытается) индексировать 1+num
th foo
в массиве. Я почти уверен, что это , а не , что вы хотите. Когда вы выделяете данные, вы передаете sizeof(foo)+num+MAX_COMMENT_SIZE
, поэтому вы выделяете место для num char
с, и вам (предположительно) нужно указать f->comment
на область памяти, которая является num char
s после f->data
, что было бы больше так:
f->comment = (char *)f + sizeof(foo) + num;
Приведение f
к char *
заставляет выполнять математику в терминах char
с вместо foo
с.
OTOH, так как вы всегда выделяете MAX_COMMENT_SIZE
для comment
, я бы, вероятно, немного упростил вещи и использовал бы что-то вроде этого:
typedef struct foo {
char comment[MAX_COMMENT_SIZE];
size_t num_foo;
char data[1];
}foo;
А затем распределите его следующим образом:
foo *f = malloc(sizeof(foo) + num-1);
f->num_foo = num;
и он будет работать без каких-либо манипуляций с указателями. Если у вас есть компилятор C99, вы можете немного изменить это:
typedef struct foo {
char comment[MAX_COMMENT_SIZE];
size_t num_foo;
char data[];
}foo;
и выделить:
foo *f = malloc(sizeof(foo) + num);
f->num_foo = num;
Это дает дополнительное преимущество, заключающееся в том, что стандарт на самом деле его благословляет, хотя в этом случае преимущество довольно незначительное (я думаю, что версия с data[1]
будет работать с каждым существующим компилятором C89 / 90).