c - C 中 1 的无效写入大小

标签 c

我尝试使用链表在 C 中编写一个队列(字符串版本)程序。

结构如下:

struct strqueue;
typedef struct strqueue *StrQueue;

struct node {
  char *item;
  struct node *next;
};

struct strqueue {
  struct node *front;//first element
  struct node *back;//last element in the list
  int length;
};

我先创建一个新的StrQueue

StrQueue create_StrQueue(void) {
  StrQueue q = malloc(sizeof (struct strqueue));
  q->front = NULL;
  q->back = NULL;
  q->length = 0;
  return q;
}

复制str并将其放在队列的末尾

void push(StrQueue sq, const char *str) {
  struct node *new = malloc(sizeof(struct node));
  new->item = NULL;
  strcpy(new->item,str);//invalid write size of 1 ?
  new->next = NULL;
  if (sq->length == 0) {
  sq->front = new;
  sq->back = new;
} else {
  sq->back->next = new;
  sq->back = new;
}
sq->length++;
}

释放 sq 前面的节点并返回队列中第一个的字符串

char *pop(StrQueue sq) {
 if (sq->length == 0) {
 return NULL;
}
 struct node *i = sq->front;
 char *new = sq->front->item;
 sq->front = i->next;
 sq->length --;
 free(sq->front);
 return new;
}

我在 strcpy(new->item,str) 处得到无效的写入大小 1;我不明白为什么会出现此错误。 谁能告诉我为什么并告诉我该如何解决?提前致谢。

最佳答案

好吧,首先,在下面的答案中,我不会修复你的双向链表概念,我只是向你展示你应该如何在你的问题范围内修复上面的代码。您可能想了解双向链表是如何完成的。

在:

void push(StrQueue sq, const char *str) {
  struct node *new = malloc(sizeof(struct node));
  new->item = NULL;

下一句是错误的:

  strcpy(new->item,str);

有两种解决方法:

  1. 确保在使用列表时 *str 是列表管理上下文之外的有效指针。
  2. 让列表管理字符串分配(以及可能的释放)。

    1. 是一种快速而肮脏的方法,以后调试起来更容易,但较大的代码库会使它变得麻烦。
    2. 看起来更简洁的代码,但需要初始设置规则,除了列表管理例程之外,您还应该创建对象(字符串)管理例程。本身可能很麻烦。

案例 1:const char *str 保证在 StrQueue 的生命周期内有效(这才是您真正需要的)

应该是:

new->item = str;

这里我们假设 str 是在别处分配的动态字符串

现在,在 pop 中,当您弹开绳子时就可以了。因为你返回的指针仍然有效(你在别处保证它)

案例 2:const char *str 不保证在 StrQueue 的生命周期内有效

然后使用:

new->item = strdup(str);

现在,在 pop 中,当您弹出字符串时,您可以

  1. 取消分配 strdup 并且不返回任何东西,(与您所做的不完全相同)
  2. 将容器指针传递给 pop,其中 item 的内容被复制(干净)
  3. 返回弹出的指针,但是当你用完它时你必须单独释放它(丑陋的)

这将使您的 pop 函数成为以下之一:

案例2.1:

 void pop(StrQueue sq) {

    if (sq->length == 0) {
       return NULL;
    }
    struct node *node = sq->front;
    sq->front = node->next;
    sq->length--;
    free(node->item);
    free(node);
}

案例2.2:

 char *pop(StrQueue sq, char *here) {

    if (sq->length == 0) {
       return NULL;
    }
    struct node *node = sq->front;
    sq->front = node->next;
    sq->length--;
    strcpy(here, node->item);
    free(node->item);
    free(node);
}

案例2.3:

 char *pop(StrQueue sq) {

    char *dangling_item = NULL;
    if (sq->length == 0) {
       return NULL;
    }
    struct node *node = sq->front;
    sq->front = node->next;
    sq->length--;
    dangling_item = node->item;
    free(node);
    return dangling_item;
}

关于c - C 中 1 的无效写入大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17903833/

相关文章:

c - 如何同时使用 scanf 和 fgets 读取文件

objective-c - 网络拓扑信息

Python/C API gcc 编译警告未使用的变量

CRC 16程序计算校验和

C 中将 char * 转换为 unsigned char 数组

c - 在 C 中将数组中的数字排序为列和行

即使分配了内存,修改链表的 C 程序也会导致段错误

c++ - 可以打开小的 ASCII 文件,但不能打开大的二进制文件吗?

c - 不明白这个递归函数

c - 如何仅使用 C 标准库获取文件列表