【问题标题】:get segmentation fault error when use strcpy function使用 strcpy 函数时出现分段错误错误
【发布时间】:2020-04-20 08:14:13
【问题描述】:

我正在实现双向链表,在函数 create_head_node、insert_head、insert_tail 中,我必须将数组名称复制到节点。然后我使用函数 strcpy 复制它,但出现 segmentation fault 错误。我通过 cpystr 重新实现了函数 strcpy,然后在 dest[i]=source[i]; 处出现分段错误错误。任何人都可以向我解释为什么它是错误的以及如何解决它。感谢您的帮助。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct linked_list
{
    char name[30];
    float point;
    struct linked_list *p_node;
    struct linked_list *n_node;
}node;

node *create_head_node(node *,char *, float);
node *insert_head(node *, char*, float);
void insert_tail(node *, char*, float);
node *insert_after(node *, char*, float, int);
int count_node(node *);
void print_list(node *);
void cpystr(char*, char*);

int main(){
    node *head=(node*)malloc(sizeof(node));
    head=create_head_node(head, "asd fgh", 10);
    head=insert_head(head, "abc def", 9.8);
    insert_tail(head, "qwe rty", 8.98);
    head=insert_after(head, "ui op", 8.7568, 1);
    print_list(head);
    free(head);
    return 0;
}
node *create_head_node(node *head, char name[30], float point){
    cpystr(head->name, name);
    head->point=point;
    head->p_node=NULL;
    head->n_node=NULL;
    return head;
}
node *insert_head(node *head, char name[30], float point){
    node *temp=(node*)malloc(sizeof(node));
    cpystr(temp->name, name);
    temp->point=point;
    temp->p_node=NULL;
    temp->n_node=head;
    head->p_node=temp;
    head=temp;
    return head;
}
void insert_tail(node *head, char name[30], float point){
    node *p=head;
    node *temp=(node*)malloc(sizeof(node));
    cpystr(temp->name, name);
    temp->point=point;
    temp->n_node=NULL;
    while (p!=NULL)
    {
        p=p->n_node;
    }
    p->n_node=temp;
    temp->p_node=p;
}
node *insert_after(node *head, char name[30], float point, int index){
    int count=count_node(head);
    while (index>count)
    {
        printf("choose %d positions to add. choose again: ", count); scanf("%d", index);
    }
    if(index==0) head=insert_head(head, name, point);
    else if(index==count) insert_tail(head, name, point);
    else{
        node *p=head;
        for (int i = 0; i < index-1; i++)
        {
            p=p->n_node;
        }
        node *temp=(node*)malloc(sizeof(node));
        temp->n_node=p->n_node;
        p->n_node->p_node=temp;
        p->n_node=temp;
        temp->p_node=p;
    }
    return head;
}
int count_node(node *head){
    node *p=head;
    int count=0;
    while (p!=NULL)
    {
        count++;
        p=p->n_node;
    }
    free(p);
    return count;
}
void print_list(node *head){
    node *p=head;
    while (p!=NULL)
    {
        printf("%s%10f", p->name, p->point);
        p=p->n_node;
    }
}
void cpystr(char* dest, char* source){
    int i=0;
    while (source[i]!='\0')
    {
        dest[i]=source[i];
        i++;
    }
    *dest='\0';
}

【问题讨论】:

  • node *head; head=create_head_node(head, "viet anh", 10); head 变量未初始化,但在 create_head_node 中被取消引用。这是未定义的行为,并且经常(但不总是)导致段错误。
  • headcreate_head_node 中的哪些位置被取消引用。
  • 以及为什么调试器会在 cpystr 函数中显示 seg 错误? @kaylum
  • head-&gt;namehead-&gt;pointhead-&gt;p_nodehead-&gt;n_node。带有head-&gt; 的任何内容都是该指针的取消引用。
  • 一旦触发了未定义的行为,我们就无法预期行为会是什么。因此,段错误(或任何其他行为)可能发生在未定义行为首次发生的任何点。

标签: c struct strcpy


【解决方案1】:

让我们考虑一下指针的一般工作原理。指针是变量,其值包含另一个变量的地址。因此,必须先初始化指针,也就是“它应该指向的变量的分配地址”,然后才能使用它们。现在,当您执行node* head 时。 head 还没有初始化,你必须为 head 分配内存并将它的地址与 head 关联起来,像这样:

    node *head = (node*)malloc( sizeof(node) );

现在你可以像这样访问 head 的成员了:

     head->point = 0.01;

同样,strcpy 也会这样工作:

     const char *dummy = "Sample";
     strcpy(head->name , dummy);

请注意 strcpy 不检查目的地的大小。因此,如果目标指针不够大,无法接收“副本”,则可能会发生未定义的行为,并且经常但并不总是导致分段错误。

【讨论】:

    【解决方案2】:

    关于:

    node *temp=(node*)malloc(sizeof(node));
    cpystr(temp->name, name);
    

    node *create_head_node(node *head, char name[30], float point){
    cpystr(head->name, name);
    

    和类似的陈述:

    最好检查一下(通过strlen( name ),长度是

    然后使用:strncpy( head-&gt;name, name, sizeof( node.name )); 以确保结构中的name 字段不会溢出

    【讨论】:

      猜你喜欢
      • 2018-12-15
      • 2019-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 2020-02-28
      • 1970-01-01
      相关资源
      最近更新 更多