c - 在 C 中扩展动态数组并且没有任何返回

标签 c arrays malloc

这里是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->cardsCards 数组,而不是 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/

相关文章:

c - 下面的内存分配有什么不同吗?

c 的自定义 malloc 函数

c - 如何捕获传入的数据包?

c - 使用类函数宏检查变量是否已定义

python - 用python和C计算数字的不同效率

c - 在 C 中动态分配的结构中使用位域可以吗?

c++ - 为什么分配给堆栈中的局部变量的内存比 C++ 中所需的多?

ios - 在 Swift 中创建线程安全数组

PHP -> MySQL 不返回数据

java - 通过修改数组在数组中复制零