这里是C菜鸟。我有一些代码在 main() 中时工作正常,但当我开始将其分解时,它就死了。我知道这很简单,我缺少一些关键元素,而且我只需要显示一次(我保证!)。所以这里是:
在 types.h 中:
typedef struct {
char *orig_str; // various ints snipped for clarity
} Card;
typedef struct {
size_t num_cards;
Card *cards; // same here
} Deck;
在main.c中:
int main(int argc, char **argv) {
Deck deck;
// clipped the part opening input_fp, it's working fine
read_deck(&deck, input_fp);
for(int i = 0; i < deck.num_cards; i++) {
fprintf("%s", deck.cards[i].orig_str);
}
}
在 input.c 中,我将之前的代码移至 main
中:
void read_deck(Deck *deck, FILE *pfile) {
Card *card = NULL;
char line_buf[MAX_LINE_LEN];
int line_len;
while(TRUE) {
if(read_line(line_buf, input_fp) == EOF) break;
line_len = strlen(line_buf);
/* make a new card and copy in the text */
card = calloc(1, sizeof(Card));
card->orig_str = calloc(1, line_len * sizeof(char));
strcpy(card->orig_str, line_buf);
/* calloc/realloc the deck and add this card to it */
if(deck->num_cards == 0) {
deck->num_cards++;
deck->cards = calloc(1, sizeof(Card *));
} else {
deck->num_cards++;
deck->cards = realloc(deck->cards, deck->num_cards*sizeof(Card *));
}
deck->cards[deck->num_cards - 1] = *card;
}
}
当我在 read_deck
内的 gdb 中进行跟踪时,一切看起来都很好,我可以:
p deck->cards[0].orig_str = "CM TESTEX5"
p deck->cards[1].orig_str = "CM YAGI TEST"
p deck->cards[2].orig_str = "CM 78 SEGMENTS. SIGMA"
但是当循环完成并返回到 main
时,除 [0] 之外的大多数卡片不再具有值:
p deck->cards[0].orig_str = "CM TESTEX5"
p deck->cards[1].orig_str = ""
p deck->cards[2].orig_str = ""
再深入一点,我可以看到来自非常不同的卡的有效数据位 - 卡 24 orig_str 看起来不错,但它的数据来自卡 30!下次我运行它时,该数据位于卡 20 中。
我认为问题是我分配了错误大小的东西,因此数组或字符串指针是错误的。但为什么这只发生在方法结束时呢?
好吧,我做错了什么?
最佳答案
deck->cards
是 Cards
数组,而不是 Card *
数组,因此您的分配不正确。
calloc(1, sizeof(Card *));
只为指向卡片的指针分配空间,但您需要为 Card
对象分配空间。更改为
calloc(1, sizeof(Card));.
与realloc
相同
但是,由于您已经在堆上分配了Card
card = calloc(1, sizeof(Card));
您可以将数组的类型更改为 Card **
并将这些指针存储在数组中
deck->cards[deck->num_cards - 1] = card;
但我认为您不想这样做,因此您可以忽略它。
您不需要在堆上分配临时Card
。您只需将局部变量更改为:
Card card;
并完全消除card = calloc(1, sizeof(Card));
。事实上,你有内存泄漏,因为你从来没有释放
它们,但这样你就不需要担心这个问题。
最后一点,deck->cards[deck->num_cards - 1] = *card;
进行浅复制。这可能是也可能不是问题。不能用简化的代码确定。
更新功能:
void read_deck(Deck *deck, FILE *pfile) {
Card card; // No longer a pointer
char line_buf[MAX_LINE_LEN];
int line_len;
while(TRUE) {
if(read_line(line_buf, input_fp) == EOF) break;
line_len = strlen(line_buf);
/* make a new card and copy in the text */
// You weren't allocating space for the '\0' so +1 added
card.orig_str = calloc(1, (line_len + 1) * sizeof(char));
strcpy(card->orig_str, line_buf);
/* calloc/realloc the deck and add this card to it */
if(deck->num_cards == 0) {
deck->num_cards++;
deck->cards = calloc(1, sizeof(Card));
} else {
deck->num_cards++;
deck->cards = realloc(deck->cards, deck->num_cards*sizeof(Card));
}
// Shallow copy temp object to array
deck->cards[deck->num_cards - 1] = card;
}
}
我还应该提到,使用 NULL
指针调用 realloc
与调用 malloc
相同,因此您可以通过仅使用1 个分配。
关于c - 在 C 中扩展动态数组并且没有任何返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49162020/