【问题标题】:Linked List - Segmentation Fault链表 - 分段错误
【发布时间】:2015-10-21 20:01:34
【问题描述】:

这段代码应该是由用户输入的十个名字组成的链接列表 它应该打印出该列表。

#include<stdio.h>
#include<stdlib.h>
struct NameList
{
    char *name;
    struct NameList *nname;
};
typedef struct NameList NL;

int main()
{
    int i;
    NL *first;
    NL *next;
    first = (NL*)malloc(sizeof(NL));
    if (first ==NULL)
            printf("Memory not properly allocated\n");
    NL *pNames;
    pNames =  first;
    for(i = 0; i<10; i++)
    {
            printf("Enter a name: ");
            scanf("%s", &pNames->name);
            if(i == 9)
                    next = NULL;
            else
                    next = (NL*)malloc(sizeof(NL));
            pNames->nname = next;
            pNames = pNames->nname;
    }

到这里都没有问题,我输入了十个名字但是一输入 我得到一个分段错误的姓氏。 我猜它来自这里,但我完全不确定

        pNames = first;
        while(pNames != NULL)
        {
                printf("%s\n", pNames->name);
                pNames = pNames->nname;
        }


    }

【问题讨论】:

  • 使用调试器逐行执行。这有助于理解这类问题。
  • 如果first == NULL,您应该退出。
  • 我的 C 有点生锈了,但是你确定不需要在 scanf 之前为 name 分配空间吗?
  • 在写入每个结构之前,您应该为 (char *name) 分配内存。
  • @FiddlingBits 但是我将 pNames = 设置为 first,当 pNames (first) 不等于 NULL 时运行 while 循环,这意味着它在 pNames 等于 NULL 时退出

标签: c linked-list


【解决方案1】:

这一行是源代码:

printf("Enter a name: ");
scanf("%s", &pNames->name);

最好像这样创建一个静态缓冲区:

char buf[20];

然后

printf("Enter a name: ");
scanf("%s", buf);

终于:

pNames->name = strdup(buf);

编辑:为了完整起见,存在缓冲区溢出的风险。其中超过某些字符超出缓冲区的末尾会导致未定义的行为。这可以按照 @ebyrob 的建议以这种方式缓解

fgets(buf, 20, stdin);

【讨论】:

  • 更好的是 fgets(buf, 20, stdin) 以避免缓冲区溢出。
【解决方案2】:
allocate space for "name", preferably use std::string

    you need to get "next" node.

      for(i = 0; i<10; i++)
            {
                    printf("Enter a name: ");
                    scanf("%s", &pNames->name);
                    if(i == 9)
                            next = NULL;
                    else
                            next = (NL*)malloc(sizeof(NL));
                    pNames->nname = next;
                    pNames = next;
            }

              pNames = first;
                while(pNames != NULL)
                {
                        printf("%s\n", pNames->name);
                        pNames = pNames->next;
                }

【讨论】:

  • 为了保持一致性,最好不要将 C++ 的命名空间与标记为 C 的 OP 的问题混在一起。
【解决方案3】:

您尚未分配内存来保存NameList 对象的name 字段。 name 字段的类型为 char *,它有足够的空间容纳指针,而不是字符串。当您执行 scanf(%s, &amp;pNames-&gt;name); 时,您是在告诉 scanf 将名称写入该内存位置,但这将覆盖比存储指针所需的字节多得多的内容。

相反,您可以先将scanf 加载到一个临时数组中,然后malloc 有足够的空间来容纳它

char *tempbuff = malloc(128); // or some large enough buffer
for (i = 0; i<10; ++i) {
    // load the input into tempbuff first
    scanf("%s", tempbuff);
    // now make room for the string in the current object
    pNames->name = malloc(strlen(tempbuff)+1); // leave room for trailing null
    // now copy it from the tempbuff to its new home
    strcpy(pNames->name,tempbuff);
    .... // rest of code

【讨论】:

    猜你喜欢
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    相关资源
    最近更新 更多