gpt4 book ai didi

c - 段错误/列表初始化

转载 作者:行者123 更新时间:2023-11-30 19:03:46 24 4
gpt4 key购买 nike

我想创建一个具有以下结构的列表:

  • list.h:包含函数原型(prototype)并定义数据类型
  • lt.c:测试列表的主函数
  • list.c:列表的实际实现

执行时我总是收到段错误。当尝试用 gdb 识别它时,显示这是 lt.c 中以下行的错误:

list_t *li=list_init();

我的 lt.c 文件的其余部分如下所示:

#include <stdio.h>
#include <stdlib.h>
#include "list.h"

int main ( int argc, char *argv [ ], char *envp [ ] )
{
list_t *li=list_init();
//li=list_init();
/* if((li=list_init())==NULL)
{
perror (" Cannot allocate memory" ) ;
exit(-1);
}*/
}

我对list.c函数list_init()的实现如下:

list_t *list_init ()
{
list_t* newlist = malloc(sizeof(*newlist));
if (!newlist)
{
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}`enter code here`
//newlist->first=NULL;
//newlist->last=NULL;
newlist->first = (struct list_elem *) malloc(sizeof(struct list_elem));
newlist->last = (struct list_elem *) malloc(sizeof(struct list_elem));
return newlist;
}

我的list.h文件如下:

    struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();

但是,我不知道如何更改实现以使其不再发生。非常感谢您的帮助。

最佳答案

虽然不可能准确判断您的问题出在哪里,但我怀疑问题出在两个地方之一。第一,您使用字符串文字初始化每个 data 成员,该字符串文字在除极少数系统之外的所有系统上都是只读的。因此,如果您尝试在代码中的任何位置修改data,则可能会出现 SegFault。如果您稍后尝试free (pointer->data);

,同样适用

第二,您未能正确分配 node->next 指针,导致您的遍历尝试取消引用 NULL 指针或不确定指针导致相同的SegFault。如果您的 append 函数无法正确处理 if (!list->first) { ... } 情况或 else ,则可能会发生这种情况在这种情况下,您需要设置 pointer->next = newnode;

除非你发布A Minimal, Complete, and Verifiable Example (MCVE),否则真的没有办法分辨。 ,但鉴于列表操作有些通用,您可以使用类似于以下内容的 init()append() 函数(添加了 >print()free() 函数是为了更好的措施而引入的),例如

#include <stdio.h>
#include <stdlib.h>

struct list_elem {
struct list_elem *next; // Zeiger auf das naechste Element
char *data; // Zeiger auf ein Datenobject
};

typedef struct list {
struct list_elem *first;// erstes Element in der Liste
struct list_elem *last; // letztes Element in der Liste
} list_t;

/* function prototypes */
list_t *list_init ();
struct list_elem *list_append (list_t *list, char *data);
void list_print (list_t *list);
void list_free (list_t *list);

int main (void)
{
list_t *li = list_init();

if (list_append (li, (char[]){"erstes"}) == NULL ||
list_append (li, (char[]){"zweites"}) == NULL ||
list_append (li, (char[]){"drittes"}) == NULL) {
perror ("Cannot allocate memory" ) ;
exit (EXIT_FAILURE);
}

list_print (li);
list_free (li);

exit (EXIT_SUCCESS);
}

list_t *list_init (void)
{
list_t *newlist = malloc (sizeof *newlist);

if (!newlist) {
perror ("malloc-newlist");
exit (EXIT_FAILURE);
}

newlist->first = NULL;
newlist->last = NULL;

return newlist;
}

struct list_elem *list_append (list_t *list, char *data)
{
struct list_elem *node = NULL;

if (!list)
return NULL;

if (!(node = malloc (sizeof *node))) {
perror ("malloc-node");
return NULL;
}
node->data = data;
node->next = NULL;

if (!list->first)
list->first = node;
else {
struct list_elem *iter = list->first;
while (iter->next)
iter = iter->next;
iter->next = node;
}

return (list->last = node);
}

void list_print (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
printf ("%s\n", iter->data);
iter = iter->next;
}
}

void list_free (list_t *list)
{
struct list_elem *iter = NULL;

if (!list)
return;

iter = list->first;

while (iter) {
struct list_elem *victim = iter;
iter = iter->next;
free (victim);
}

free (list);
}

示例使用/输出

$ ./bin/ll_list_elem
erstes
zweites
drittes

内存使用/错误检查

不需要强制转换malloc的返回值,这是不必要的。请参阅:Do I cast the result of malloc?

在您编写的动态分配内存的任何代码中,对于分配的任何内存块,您都有 2 个责任:(1) 始终保留指向起始地址的指针内存块,因此,(2) 当不再需要它时可以释放

您必须使用内存错误检查程序来确保您不会尝试访问内存或在分配的 block 的范围之外进行写入,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。

对于 Linux,valgrind 是正常选择。每个平台都有类似的内存检查器。它们使用起来都很简单,只需通过它运行您的程序即可。

$ valgrind ./bin/ll_list_elem
==22383== Memcheck, a memory error detector
==22383== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22383== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22383== Command: ./bin/ll_list_elem
==22383==
erstes
zweites
drittes
==22383==
==22383== HEAP SUMMARY:
==22383== in use at exit: 0 bytes in 0 blocks
==22383== total heap usage: 4 allocs, 4 frees, 64 bytes allocated
==22383==
==22383== All heap blocks were freed -- no leaks are possible
==22383==
==22383== For counts of detected and suppressed errors, rerun with: -v
==22383== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认您已释放分配的所有内存并且不存在内存错误。

在前向链接中使用last指针

由于您有一个last指针,因此不需要对列表进行通用迭代来查找最后一个指针。我怀疑您打算使用前向链接。在这种情况下,您只需修改 append() 即可,如下所示:

    if (!list->first)
list->first = node;
else
list->last->next = node;

(注意:list->last = node 赋值在return 中处理)

关于c - 段错误/列表初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53440775/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com