C中写入大小无效1

时间:2013-07-28 00:32:01

标签: c

我尝试使用链接列表在C中编写队列(String Version)程序。

这是结构:

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时无效;我不明白为什么我得到这个错误。 任何人都可以告诉我为什么,并告诉我应该如何解决它?提前谢谢。

2 个答案:

答案 0 :(得分:5)

好的,首先,在下面的答案中我没有修复你的双链表概念,我只是告诉你如何在你的问题范围内修改上面的代码。您可能想要了解双链表的完成方式。

在:

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. 看起来更干净的代码,但需要初始设置规则,除了列表管理例程之外,还应创建对象(字符串)管理例程。本身就很麻烦。
  3. 案例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. 返回弹出的指针,但是当你完成它时你必须单独解除分配(丑陋)
    4. 这将使您的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;
      }
      

答案 1 :(得分:1)

我无效write size of 1 at strcpy(new->item,str);我不明白为什么会收到此错误。任何人都可以告诉我为什么并告诉我我应该如何修复

<强>为什么:

此代码:

new->item = NULL;
strcpy(new->item,str);//invalid write size of 1 ?

您不应该将空指针传递给第一个参数,它应该是指向已分配内存的指针。您可以想象,您收到此错误消息的原因是因为strcpy的实现可能如下所示:

for (int i = 0; str2[i]; i++) str1[i] = str2[i];

for循环的第一次迭代中,它写入地址0(内存的只读部分) - 这将为您提供invalid write of size 1。但是,我不确定为什么你只得到1的大小(我想它会是字符串的整个大小)。这可能是因为 a) str的大小只有1 b),因为信号SIGSEGV会停止程序。

如何解决:

在调用new->item之前为strcpy分配空格,如下所示:

new->item = malloc (strlen (str) + 1); // + 1 for null-terminating character

但你可能会包含一些错误检查,如下所示:

int len = strlen (str) + 1;
if (len){
    new->item = malloc (len);
    if (!new->item){
        return;
    }
}