Valgrind 内存错误(大小为 24 的块内有 0 个字节已释放)

Valgrind Memory Errors (0 bytes inside a block of size 24 free'd)

我从 valgrind 收到 25 个错误。其中 23 个错误来自同一上下文。我没有失忆,但我无法弄清楚确切的问题出在哪里。我得到了我想要的确切输出,但我仍然无法解决内存错误。

我添加了我的 valgrind 输出和相关代码部分。

Valgrind 输出

HEAP SUMMARY:
==30142==     in use at exit: 0 bytes in 0 blocks
==30142==   total heap usage: 76 allocs, 77 frees, 2,146 bytes allocated
==30142== 
==30142== All heap blocks were freed -- no leaks are possible
==30142== 
==30142== ERROR SUMMARY: 25 errors from 3 contexts (suppressed: 0 from 0)
==30142== 
==30142== 1 errors in context 1 of 3:
==30142== Invalid free() / delete / delete[] / realloc()
==30142==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==30142==    by 0x400D79: main (pa2.c:201)
==30142==  Address 0x52063e0 is 0 bytes inside a block of size 24 free'd
==30142==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==30142==    by 0x4009D6: byte_to_char (pa2.c:75)
==30142==    by 0x400CBC: main (pa2.c:157)
==30142==  Block was alloc'd at
==30142==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==30142==    by 0x400DE6: createNode (tree.c:10)
==30142==    by 0x4009B3: byte_to_char (pa2.c:73)
==30142==    by 0x400CBC: main (pa2.c:157)
==30142== 
==30142== 
==30142== 1 errors in context 2 of 3:
==30142== Invalid read of size 1
==30142==    at 0x400F0A: peek (stack.c:27)
==30142==    by 0x40083C: remove_zeroes (pa2.c:27)
==30142==    by 0x400CCE: main (pa2.c:165)
==30142==  Address 0x5206490 is 0 bytes inside a block of size 24 free'd
==30142==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==30142==    by 0x4008E5: byte_to_char (pa2.c:50)
==30142==    by 0x400CBC: main (pa2.c:157)
==30142==  Block was alloc'd at
==30142==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==30142==    by 0x400DE6: createNode (tree.c:10)
==30142==    by 0x4008C2: byte_to_char (pa2.c:48)
==30142==    by 0x400CBC: main (pa2.c:157)
==30142== 
==30142== 
==30142== 23 errors in context 3 of 3:
==30142== Invalid read of size 1
==30142==    at 0x400D1F: main (pa2.c:175)
==30142==  Address 0x52063e0 is 0 bytes inside a block of size 24 free'd
==30142==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==30142==    by 0x4009D6: byte_to_char (pa2.c:75)
==30142==    by 0x400CBC: main (pa2.c:157)
==30142==  Block was alloc'd at
==30142==    at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==30142==    by 0x400DE6: createNode (tree.c:10)
==30142==    by 0x4009B3: byte_to_char (pa2.c:73)
==30142==    by 0x400CBC: main (pa2.c:157)
==30142== 
==30142== ERROR SUMMARY: 25 errors from 3 contexts (suppressed: 0 from 0)

主函数调用(及之后)

int main(int argc, char ** argv){
        printf("In Main\n");
        if(argc != 7){
            printf("args doesn't match expected value\n");
            return EXIT_FAILURE;
        }
        FILE *fptr = fopen(argv[1], "rb");
        if(fptr == NULL){
            return EXIT_FAILURE;
        }
        long int size_compressed; //size_compressed: Number of bytes in compressed file
        long int size_topology;   //size_topology: Number of bytes topology uses
        long int size_original;   //size_original: Number of bytes in the uncompressed file
    
        fread(&size_compressed, sizeof(long int) , 1, fptr);
        fread(&size_topology, sizeof(long int), 1, fptr);
        fread(&size_original, sizeof(long int), 1, fptr);
        int size = sizeof(char)* sizeof(long int) * size_topology;
    
        printf("Size Compressed: %ld\n", size_compressed);
        printf("Size Topology: %ld\n", size_topology);
        printf("Size Original: %ld\n", size_original);
        
        unsigned char *buffer;
        int *val; 
        buffer = (unsigned char*) malloc(sizeof(unsigned char) * size_topology);
        size_t bytes_read = fread(buffer, sizeof(unsigned char), size_topology, fptr);
        //val = (int*) malloc(sizeof(int) * (size_topology));
        val = (int*) malloc(size);
        fclose(fptr);
    
        if(bytes_read != size_topology){
            printf("Topology size and read bytes don't match!");
        }
    
        for(int i=0; i < size_topology; i++){
          val[i] = buffer[i];
        }
    
        char *toVal; //toVal: char array of 8 to store every bit of a byte
        char *all_topology;  //all_topology: char array of 8 * size_topology to store ALL bits of topology. 
        int j; //j: index for all_topology
        // toVal = (char*) malloc(sizeof(char)* sizeof(int));
        // all_topology = (char*) malloc(size);
        toVal = (char*) malloc(size);
        all_topology = (char*) malloc(size);
    
        //For Loop where conversion of the bytes in val to bits happen, output is stored in all_topology 
        for(int i=0; i < size_topology; i++){
            j = i*8;
            byte_to_bits(val[i], toVal);
            for(int k=0; k< 8;k++){
                all_topology[j] = toVal[k];
                printf("%d", all_topology[j]);
                j++;
            }
            printf("\n");
        }
        
    
    //-----NO MEMORY ISSUES UP TO HERE-----
    //-----NO MEMORY ISSUES UP TO HERE-----
    //-----NO MEMORY ISSUES UP TO HERE-----

    Snode* stack = NULL;
    //LEAK STARTS HERE
    
    int numOfBytes = byte_to_char(all_topology, &stack, size);
    remove_zeroes(&stack);
    
    printf("NumOfBYtes: %d\n", numOfBytes);
    Tnode* node = NULL;
    Snode* reverse_stack = NULL;
    int flag = 1;
    while(flag){
        node = pop(&stack);
        if(node == NULL){
            break;
        }
        printf("%c", node->id);
        printf("\n");
        push(&reverse_stack, node); 
    }

    //FREE

    Tnode* tmp = NULL;
    while(1){
        if(isEmpty(reverse_stack)){
            break;
        } else{
            tmp = pop(&reverse_stack);
        }
    }

    free(tmp);
    free(all_topology);
    free(toVal);
    free(buffer);
    free(val);
    return EXIT_SUCCESS;
}

byte_to_char

int byte_to_char(char *topology, Snode** stack, int size){
    int numOfBytes = 0;
    char ascii_concat[8]; 
    unsigned char ascii_val = 0;  
    int countChar =0;
    Tnode* node = NULL;
    Tnode* node1 = NULL;
    Tnode* node2 = NULL;
    //char char_top[80];
    for(int i=0; i < size; i++){
        if(topology[i] == 0){
            //char_top[i] = 48; //ASCII Value of 0
            node = createNode(48, 0);
            push(stack, node);
            free(node);
            numOfBytes++;
        } else{
            ascii_val = 0xff;
            //char_top[i] = 49; //ASCII Value of 1
            node1 = createNode(49, 1);
            push(stack, node1);
            free(node1);
            numOfBytes++;
            i++; //skip the leaf node indicator
            countChar++;  
            for(int j=0; j<8; j++){
                ascii_concat[j] = topology[i++];
            }
            i--;
            for(int j=0; j<8; j++){
                if(ascii_concat[j] == 0){
                    ascii_val = (1 << (j)) ^ ascii_val;
                }
            }
            //printf("%c\n", ascii_val);
            //Create leaf node
            //char_top[i] = ascii_val;

            //byte_to_char (pa2.c:73)
            node2 = createNode(ascii_val, 2);
            push(stack, node2);
            free(node2);

            numOfBytes = numOfBytes + 8;
            //count characters in header
        }
        countChar++;
    }

    // printf("chars\n");
    // for(int i=0;i < 24; i++){
    //    printf("%c", char_top[i]);
    // }
    // free(node);
    return numOfBytes;
    
}

创建节点

Tnode* createNode(char id, int flag){
   Tnode* n = (Tnode*) calloc(1, sizeof(Tnode));
   //Tnode* n = (Tnode*) malloc(sizeof(Tnode));
   n->id = id;
   n->flag = flag;
   return n;
}

所有这三个错误上下文都是由于代码中的 2 个地方造成的,您在将节点放入堆栈后将其删除:

for(int i=0; i < size; i++){
    if(topology[i] == 0){
        //char_top[i] = 48; //ASCII Value of 0
        node = createNode(48, 0);
        push(stack, node);
        free(node);                // the target of node is still referenced
        numOfBytes++;
    } else{
        ascii_val = 0xff;
        //char_top[i] = 49; //ASCII Value of 1
        node1 = createNode(49, 1);
        push(stack, node1);
        free(node1);                 // the target of node is still referenced

您需要删除这两个对 free 的调用,而不是 free 节点,直到堆栈上的引用被弹出。