我有一个奇怪的错误我的计划,在我看来,似乎malloc()造成的一个"SIGSEGV",其中就我的理解去没有任何意义。我使用一个图书馆被称为simclist的动态名单。

这里是一个结构中引用之后:

typedef struct {
    int msgid;
    int status;
    void* udata;
    list_t queue;
} msg_t;

这里是代码:

msg_t* msg = (msg_t*) malloc( sizeof( msg_t ) );

msg->msgid = msgid;
msg->status = MSG_STAT_NEW;
msg->udata = udata;
list_init( &msg->queue );

list_init 是程序失败,这里的代码list_init:

/* list initialization */
int list_init(list_t *restrict l) {
    if (l == NULL) return -1;

    srandom((unsigned long)time(NULL));

    l->numels = 0;

    /* head/tail sentinels and mid pointer */
    l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
    l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
    l->head_sentinel->next = l->tail_sentinel;
    l->tail_sentinel->prev = l->head_sentinel;
    l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL;
    l->head_sentinel->data = l->tail_sentinel->data = NULL;

    /* iteration attributes */
    l->iter_active = 0;
    l->iter_pos = 0;
    l->iter_curentry = NULL;

    /* free-list attributes */
    l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *));
    l->spareelsnum = 0;

#ifdef SIMCLIST_WITH_THREADS
    l->threadcount = 0;
#endif

    list_attributes_setdefaults(l);

    assert(list_repOk(l));
    assert(list_attrOk(l));

    return 0;
}

线 l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * 是"SIGSEGV"是造成根据本堆踪。我使用的库/nemiver调试,但是在一个损失。第一次这种功能是所谓它工作得很好,但它总是失败的第二次。如何可以malloc()导致"SIGSEGV"?

这是堆叠跟踪:

#0  ?? () at :0
#1  malloc () at :0
#2  list_init (l=0x104f290) at src/simclist.c:205
#3  msg_new (msg_switch=0x1050dc0, msgid=8, udata=0x0) at src/msg_switch.c:218
#4  exread (sockfd=8, conn_info=0x104e0e0) at src/zimr-proxy/main.c:504
#5  zfd_select (tv_sec=0) at src/zfildes.c:124
#6  main (argc=3, argv=0x7fffcabe44f8) at src/zimr-proxy/main.c:210

任何帮助或见解非常的感谢!

有帮助吗?

解决方案

例如,当堆损坏时,

malloc会出现段错误。检查您是否正在编写超出先前分配范围的任何内容。

其他提示

代码的其他部分可能发生内存违规。如果你在Linux上,你一定要试试valgrind。我永远不会相信我自己的C程序,除非它通过valgrind。

编辑:另一个有用的工具是电围栏。 Glibc还提供 MALLOC_CHECK_ 环境变量,以帮助调试内存问题。这两种方法不像valgrind那样影响运行速度。

您可能在此调用之前通过缓冲区溢出或通过使用未由free分配的指针(或已经释放)调用malloc来破坏堆。

如果malloc使用的内部数据结构以这种方式被破坏,则malloc使用无效数据并可能崩溃。

有无数种方式的触发一个核倾倒从 malloc() (及 realloc()calloc()).这些包括:

  • 缓冲区的溢出:写作结束后分配的空间(控制践踏的信息, malloc() 就保持那里)。
  • 缓冲区的溢出:写作开始之前所分配的空间(控制践踏的信息, malloc() 就保持那里)。
  • 在释放记忆,这不是分配 malloc().在混合的C和C++的程序,这将包括释放分配的内存在C++由 new.
  • 释放一个指针指的一部分的方式通过记忆区块分配的 malloc() -这是一个特殊的情况下,前面的情况。
  • 释放一指针已经释放了-臭名昭着的'双人自由'。

使用诊断的版本 malloc() 或者使诊断系统标准的版本,可帮助识别这些问题。例如,它可能能够探测到小下溢和溢出(因为它分配额外的空间,提供一个缓冲区周围的空间,你的要求),并且它可以检测可能试图免费存储器,这不是分配或已经被释放或指针的部分方式通过所分配的空间,因为它将储存的信息分开,从所分配的空间。成本是调试版本,需要更多的空间。一个很好的分配程序将能够记录堆迹和线号码告诉你这里的分配发生在你的代码或在哪里第一个免费发生的。

您应该尝试单独调试此代码,以查看问题是否实际位于生成segfault的位置。 (我怀疑它不是)。

这意味着:

#1:使用-O0编译代码,以确保gdb获得正确的行号信息。

#2:编写一个调用此部分代码的单元测试。

我的猜测是,单独使用时代码可以正常工作。然后,您可以以相同的方式测试其他模块,直到找到导致错误的原因。

正如其他人所建议的那样,使用Valgrind也是一个非常好的主意。

代码有问题。如果malloc返回NULL,则在您的代码中无法正确处理此情况。你只是假设已经为你分配了实际上没有的内存。这可能会导致内存损坏。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top