Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can malloc() cause a SIGSEGV?

I have an odd bug in my program, it appears to me that malloc() is causing a SIGSEGV, which as far as my understanding goes does not make any sense. I am using a library called simclist for dynamic lists.

Here is a struct that is referenced later:

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

And here is the code:

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 is where the program fails, here is the code for 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;
}

the line l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * is where the SIGSEGV is caused according to the stack trace. I am using gdb/nemiver for debugging but am at a loss. The first time this function is called it works fine but it always fails the second time. How can malloc() cause a SIGSEGV?

This is the stack trace:

#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

Any help or insight is very appreciated!

like image 710
user19745 Avatar asked Sep 17 '09 19:09

user19745


People also ask

What causes SIGSEGV error?

1) Segmentation Fault (also known as SIGSEGV and is usually signal 11) occur when the program tries to write/read outside the memory allocated for it or when writing memory which can only be read.In other words when the program tries to access the memory to which it doesn't have access to.

Why does malloc cause segmentation fault?

A SIGSEGV (segmentation fault) is firing in malloc is usually caused by heap corruption. Heap corruption does not cause a segmentation fault, so you would see that only when malloc tries to access there.

How do you avoid SIGSEGV?

Don't use pointers. And if you do always check for NULL pointers. Minimize the use of pointers, access any kind of arrays within its bounds, check whether pointer is NULL before using, make sure you allocate new memory before using a pointer which you have already freed (it may not be giving NULL ).

What is SIGSEGV?

The SIGSEGV signal is raised when you attempt to illegally access or modify memory. SIGSEGV is usually caused by using uninitialized or NULL pointer values or by memory overlays. By default, SIGSEGV causes program termination with an appropriate ABEND code (0C4 for a protection error or 0C5 for an addressing error).


3 Answers

malloc can segfault for example when the heap is corrupted. Check that you are not writing anything beyond the bounds of any previous allocation.

like image 51
laalto Avatar answered Nov 01 '22 19:11

laalto


Probably memory violation occurs in other part of your code. If you are on Linux, you should definitely try valgrind. I would never trust my own C programs unless it passes valgrind.

EDIT: another useful tool is Electric fence. Glibc also provides the MALLOC_CHECK_ environmental variable to help debug memory problems. These two methods do not affect running speed as much as valgrind.

like image 35
user172818 Avatar answered Nov 01 '22 19:11

user172818


You probably have corrupted you heap somewhere before this call by a buffer overflow or by calling free with a pointer that wasn't allocated by malloc (or that was already freed).

If the internal data structures used by malloc get corrupted this way, malloc is using invalid data and might crash.

like image 26
sth Avatar answered Nov 01 '22 17:11

sth