我如何在动态分配的结构中释放()动态分配的数组

How would I free() a dynamically allocated array in a dynamically allocated struct

提问人:programme3219873 提问时间:9/9/2021 最后编辑:Jonathan Lefflerprogramme3219873 更新时间:9/9/2021 访问量:68

问:

我编写了一个程序来模拟“队列”数据结构——代码如下:

queue.h:

#ifndef QUEUE
#define QUEUE

typedef struct Q
{
  int *queue;
  int size;
  int elements;
  int end;
  int beg;

} QueueType;

QueueType *Create(int n);

int Insert_end(QueueType *q_ptr, int n);

int Remove_Beg(QueueType *q_ptr);

int Ret_First(QueueType *q_ptr);

int Ret_Last(QueueType *q_ptr);

#endif

queue.c:

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

QueueType *Create(int n)
{
    QueueType *ptr = malloc(sizeof(QueueType));
    ptr->queue = malloc(sizeof(int) * n);

    ptr->size = n;
    ptr->beg = n-1;
    ptr->end = n-2; 
    ptr->elements = 0;

    return ptr;
}

int Insert_end(QueueType *q_ptr, int n) // inserts data at end of queue
{        
   if (!(q_ptr->elements == q_ptr->size))   // "elements" is number of valid data in the queue, size is the size of the queue.
   {
     if (q_ptr->elements == 0)     // if the queue is empty
     {
        q_ptr->queue[q_ptr->size-1] = n;
        q_ptr->elements++;
     }
     else                           // if the queue is not empty
     {
        q_ptr->queue[q_ptr->end] = n;
        q_ptr->end = q_ptr->end-1;
        q_ptr->elements++;
     }
   }
   else             // if the queue is full
   {
      printf("Queue Full");
   }
}

int Remove_Beg(QueueType *q_ptr)   // removes beginning element of queue
{
    printf("\n");
    for (int *start = &(q_ptr->queue[q_ptr->beg-1]); start >= &(q_ptr->queue[q_ptr->end-1]); start--) 

    *(start+1) = *start;

// goes from start of queue to end and moves values along so the first value gets overwritten eventually (basically pops the first value and moves each value along)
}

int Ret_First(QueueType *q_ptr) // returns first queue value
{
   return q_ptr->queue[q_ptr->beg];
}

int Ret_Last(QueueType *q_ptr) // returns last queue value
{
   return q_ptr->queue[q_ptr->end];
}

main.c:

#include <stdio.h>
#include "queue.h"

int main()
{
    QueueType *ptr = Create(10);

    Insert_end(ptr,2);
    Insert_end(ptr,4);
    Insert_end(ptr,6);
    Insert_end(ptr,8);
    Insert_end(ptr,10);
    Insert_end(ptr,12);
    Insert_end(ptr,14);
    Insert_end(ptr,16);
    Insert_end(ptr,18);
    Insert_end(ptr,20);

    Remove_Beg(ptr);

    free(ptr->queue);
    free(ptr);

    return 0;
}                                                             

我的问题是,在运行 valgrind 检查内存泄漏和错误后,还剩下 40 个字节:

==4007== LEAK SUMMARY:
==4007==    definitely lost: 40 bytes in 1 blocks
==4007==    indirectly lost: 0 bytes in 0 blocks
==4007==      possibly lost: 0 bytes in 0 blocks
==4007==    still reachable: 0 bytes in 0 blocks
==4007==         suppressed: 0 bytes in 0 blocks

我只能假设这是来自使用该函数分配的 10 个整数数组。main 函数给出了错误,那么我该如何释放分配的数组以及存储数组的实际结构体呢?Create()free()

C 指针 struct malloc free

评论

2赞 Jonathan Leffler 9/9/2021
您应该能够获得有关丢失内存的更多信息 - 要么是 Valgrind 的额外选项,要么是重新编译并使用该选项重新链接您的代码并再次运行 Valgrind。如果“额外选项”是合适的,它将建议使用正确的选项。-g
0赞 Jonathan Leffler 9/9/2021
您的函数被声明为返回 ,但不返回任何内容。重新定义并重新声明它以返回 。但是,这不会影响内存泄漏。Remove_Beg()intvoid
2赞 Jonathan Leffler 9/9/2021
您应该报告错误,例如 on (not ),并且应该使用换行符终止消息: 。Queue Fullstderrstdoutfprintf(stderr, "Queue Full\n");
3赞 Jonathan Leffler 9/9/2021
当我运行您的代码的最小改编版本(也不返回值)时,我收到 2 条“读取大小 4 无效”消息和 1 条“大小 4 无效写入”消息——但没有内存泄漏。然而,这仅仅意味着未定义的行为以不同的方式表现出来。您应该仔细查看 中的代码。我不完全理解你在那里做什么,所以我不能建议你如何解决它。但是,与内存泄漏相比,内存滥用问题需要更紧迫地修复(尽管内存泄漏也需要修复)。Insert_end()Remove_Beg()Remove_Beg()
2赞 n. m. could be an AI 9/9/2021
如果你正在尝试实现一个循环缓冲区队列,那么看起来你并不完全理解它应该如何工作。特别是,中不应有循环。如果你试图实现那种移动元素的队列,那么你不清楚为什么你需要两个 和 。无论如何,中都存在缓冲区溢出,如果需要,您可以捕获它,但我建议您先研究您选择的数据结构。Remove_BegbegendRemove_Beg-fsanitize-address

答: 暂无答案