复杂数据类型的 Valgrind "Memory Error"

Valgrind "Memory Error" with complex data type

我写了一个 C 程序,它是带有链表的堆栈的通用实现。我尝试反转一些字符串、整数数组、双精度数组,并且效果很好。我使用 valgrind 检查内存泄漏和错误,仍然没有问题。但是,当我尝试反转复杂数据类型(例如结构类型)的数组时,即使没有泄漏并且输出正确,我也会收到内存错误。

所以,

  1. 我哪里做错了?

  2. Invalid write of size 8是什么意思?

  3. 还有这个 - Address 0x4e444d8 is 0 bytes after a block of size 8 alloc'd 是什么意思?

// 以下是来自 valgrind 的错误日志:

==74356== HEAP SUMMARY:
==74356==     in use at exit: 0 bytes in 0 blocks
==74356==   total heap usage: 7 allocs, 7 frees, 1,096 bytes allocated
==74356== 
==74356== All heap blocks were freed -- no leaks are possible
==74356== 
==74356== ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 0 from 0)
==74356== 
==74356== 3 errors in context 1 of 2:
==74356== Invalid read of size 8
==74356==    at 0x109425: reverse (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1092DA: main (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==  Address 0x4e44618 is 0 bytes after a block of size 8 alloc'd
==74356==    at 0x4A36ECB: malloc (vg_replace_malloc.c:307)
==74356==    by 0x109587: newNode (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x109490: push (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1093E3: reverse (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1092DA: main (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356== 
==74356== 
==74356== 3 errors in context 2 of 2:
==74356== Invalid write of size 8
==74356==    at 0x4A3E333: memmove (vg_replace_strmem.c:1270)
==74356==    by 0x1095A2: newNode (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x109490: push (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1093E3: reverse (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1092DA: main (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==  Address 0x4e444d8 is 0 bytes after a block of size 8 alloc'd
==74356==    at 0x4A36ECB: malloc (vg_replace_malloc.c:307)
==74356==    by 0x109587: newNode (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x109490: push (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1093E3: reverse (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356==    by 0x1092DA: main (in /home/arnab/MyWorkspace/c-workspace/test/generic_functions/test_node/test)
==74356== 
==74356== ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 0 from 0)

// 下面是程序 -

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

#define SIZE 3

typedef struct node{
    void * data;
    struct node * next;
}NODE;

typedef struct stack{
    NODE * top;
}STACK;


typedef struct comp{
    double real;
    double imaginary;
}COMPLEX;


NODE * newNode (void * data, size_t size);
bool isEmpty (NODE * top);
NODE * push (NODE * top, void * data, size_t size);
NODE * pop (NODE * top);

void reverse (COMPLEX arr[], int n);     

int main (void)
{   
    COMPLEX arr[SIZE] = {
                            {1.7, 2.3}, 
                            {2.4, 3.5}, 
                            {3.1, 4.8}
                        };

    printf ("Before reversing-\n");
    
    for (int i = 0; i < SIZE; i++)
        printf ("%.1lf + %.1lfi\n", arr[i].real, arr[i].imaginary);       

    reverse (arr, SIZE);

    putchar ('\n');

    printf ("After reversing-\n");

    for (int i = 0; i < SIZE; i++)
        printf ("%.1lf + %.1lfi\n", arr[i].real, arr[i].imaginary);

    return 0; 
}

void reverse (COMPLEX arr[], int n)
{
    STACK S = {.top = NULL};

    for (int i = 0; i < n; i++)
        S.top = push (S.top, &arr[i], sizeof (COMPLEX));


    for (int i = 0; i < n; i++)
    {
        * ((COMPLEX *) (&arr[i])) = * ((COMPLEX *) (S.top->data));
        S.top = pop (S.top);
    }
}


NODE * newNode (void * data, size_t size)
{
    NODE * new_Node = malloc (sizeof (NODE));
    new_Node->data = malloc (sizeof (size));
    memcpy (new_Node->data, data, size);
    new_Node->next = NULL;
    return new_Node; 
}

bool isEmpty (NODE * top)
{
    if (top == NULL)
        return true;
    
    return false;
}

NODE * push (NODE * top, void * data, size_t size)
{
    NODE * new_Node = newNode (data, size);

    if (isEmpty (top))
        top = new_Node;
    else
    {   
        new_Node->next = top;
        top = new_Node;
    }
    
    return top;
}

NODE * pop (NODE * top)
{
    if (isEmpty (top))
        fprintf (stderr, "Stack is empty. Cannot perform pop operation.\n");
    else
    {
        NODE * next = top->next;
        free (top->data);
        free (top);
        top = next;
    }

    return top;
}

What I am I doing wrong?

malloc (sizeof (size));

无效。那是 sizeof(size_t) - size 具有的类型的大小。变量 size 已经保存了某物的 大小 的值。所以只需传递 size.

new_Node->data = malloc(size);
// ^^ ugh

What does Invalid write of size 8 mean ?

这意味着您的程序试图写入不允许写入的无效内存地址。写入操作试图写入 8 个字节。

Also what does this - Address 0x4e444d8 is 0 bytes after a block of size 8 alloc'd mean ?

您为 malloc(sizeof(size)) 分配的字节数不足,但 memcpy 正试图在那里写入字节数。地址 0x4e444d8memcpy 试图写入的地址 - 它是“0 字节”/紧跟在 malloc 分配的内存之后,而你用 [=] 分配了 8 个字节20=]打电话。