Valgrind在简单队列代码中的alloc&#d;之后无效写入/地址0

时间:2017-03-17 02:15:33

标签: c valgrind

我不明白为什么队列的以下代码会使valgrind警告无效写入,并且分配后地址为0字节。代码看起来很明智,非常简单。

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

typedef struct {
    int size;
    int head;
    int count;
    int *items;
} queue_t;

void push(queue_t *q, int item) {
    if (q->count == q->size) {
        printf("overflow\n");
        exit(1);
    }
    q->items[q->count + q->head] = item;
    q->count++;
}

int pop(queue_t *q) {
    if (q->count == 0) {
        printf("underflow\n");
        exit(1);
    }
    int x = q->items[q->head];
    q->head++;
    q->head = q->head % q->size;
    q->count--;
    return x;
}

int main () {
    queue_t *q = (queue_t*) malloc(sizeof(queue_t));
    q->head = q->count = 0;
    q->size = 3;
    q->items = (int*) malloc(sizeof(int) * q->size);

    push(q,4);
    push(q,4);
    push(q,4);

    pop(q);
    push(q, 4);
    printf("%i\n", pop(q));
    free(q->items);
    free(q);
}

valgrind的输出:

==5930== Memcheck, a memory error detector
==5930== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5930== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==5930== Command: ./array-queue
==5930== 
==5930== Invalid write of size 4
==5930==    at 0x40066E: push (array-queue.c:17)
==5930==    by 0x4007B1: main (array-queue.c:44)
==5930==  Address 0x51d50ac is 0 bytes after a block of size 12 alloc'd
==5930==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5930==    by 0x400756: main (array-queue.c:37)
==5930== 
4
==5930== 
==5930== HEAP SUMMARY:
==5930==     in use at exit: 0 bytes in 0 blocks
==5930==   total heap usage: 3 allocs, 3 frees, 1,060 bytes allocated
==5930== 
==5930== All heap blocks were freed -- no leaks are possible
==5930== 
==5930== For counts of detected and suppressed errors, rerun with: -v
==5930== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

1 个答案:

答案 0 :(得分:3)

您考虑了pop函数中列表的回绕,但忘记在push函数中对其进行说明。结果,对push的第四次调用读取超出分配缓冲区的末尾。

此:

q->items[q->count + q->head] = item;

应该是:

q->items[(q->count + q->head) % q->size] = item;