C语言 调用free()释放在多个函数中被strdup() malloc(ed)占用的内存



编写了一个程序"麻烦票",允许用户创建带有各种参数的故障票。代码使用struct ticket {}来存储票证数据。每向tkt_array添加一个new_ticket。代码是相当长的,所以我张贴了相关的文件和代码片段。这不是学校的项目,而是我个人对学习c的兴趣。

总之,有函数create_ticket()update_ticket()使用_strdup()来处理用户输入。这是我的理解,_strdup()使用malloc(),这需要调用free()的内存。我的方法是在程序退出时调用free(),并假设这将释放malloc()占用的内存。此任务由free_tkt_arr()函数完成。

create_ticket()函数在设置nameproblemassigned_tostatus指针时使用_strdup()

函数update_ticket()也使用_strdup()来更新name,problem,assigned_tostatus

代码退出时,调用free_tkt_arr()函数释放_strdup()分配的内存。

我想知道在系统退出时调用free_ticket()是否会释放在create_ticket()update_ticket()中调用_strdup()所分配的所有内存?

struct ticket {
int priority;
int number;
char *name;
char *problem;
char *assigned_to;
char *status;
};

函数create_ticket()在设置name,problem,assigned_tostatus指针时使用_strdup():

struct ticket tkt_array[NUM_TICKETS];
void create_ticket() {
char *ptr;
struct ticket new_ticket;
printf("Enter your name: ");
new_ticket.name = _strdup(get_input(20));
printf("Enter problem description: ");
new_ticket.problem = _strdup(get_input(100));
printf("Assigned to: ");
new_ticket.assigned_to = _strdup(get_input(20));
//printf("Enter ticket status: ");
//using _strdup() in case status is updated using _strdup which requires call to free()
ptr = "new";
new_ticket.status = _strdup(ptr);
}

函数update_ticket()也使用_strdup()来更新name,problem,assigned_tostatus票。

void update_ticket() {
printf("Enter ticket number:  ");
ptr = get_input(8);
sscanf_s(ptr, "%d", &ticket_num);
if (*ptr == '1') {
printf("Updating Status.n");
printf("Enter Status update:  ");
tmp_ticket2.status = _strdup(get_input(20));
} else
if (*ptr == '2') {
printf("Updating Problem description.n");
printf("Enter Problem description update.  ");
tmp_ticket2.problem = _strdup(get_input(100));
} else
if (*ptr == '3') {
printf("Updating Assigned to.n");
printf("Enter Assigned to update.  ");
tmp_ticket2.assigned_to = _strdup(get_input(20));
}
}

函数free_tkt_array()在退出代码时被调用,应该被调用释放之前调用_strdup()所分配的内存

void free_tkt_arr() {
for (int i = 0; i <= tkt_count - 1; i++) {
free(tkt_array[i].assigned_to);
free(tkt_array[i].name);
free(tkt_array[i].problem);
free(tkt_array[i].status);
}
}

我想过下载和学习valgrind,但这可能有点超出我的能力范围。

是否应该释放字符串取决于get_input()做什么。如果get_input()返回一个已分配的内存块,则不需要调用strdup()

请注意,您应该使用strdup()而不是_strdup():

  • _strdup()是Microsoft特有的函数,可能实现了与POSIX标准函数strdup()相同的语义。

  • strdup()在Unix系统上可用,在POSIX中指定。它将成为即将到来的C2x版本C标准的一部分(最终)。

  • 如果strdup()在您的系统中不可用,您可以使用宏或这样定义它:

    #include <stdlib.h>
    #include <string.h>
    char *strdup(const char *s) {
    size_t size = strlen(s) + 1;
    char *p = malloc(size);
    if (p) {
    return memcpy(p, s, size);
    } else {
    return p;
    }
    }
    

您可以free()内存,但您也有传递NULL到指针,如果你不释放与结构相关的内存(似乎是这种情况)。当您在静态全局内存中分配一个结构体数组时,您将使它们全部初始化为NULL,因此不需要初始化指针来检查它们是否已被分配。但过了一段时间就不适用了,所以一旦你不使用它们,你最好把memset(3)bzero(3)改成你的结构。您没有展示如何区分已使用的记录和未使用的记录,但是如果您使用指针字段作为标志将其标记为未使用,那么您必须在释放票据后将其设置为NULL。如果不这样做,使您的指针继续指向未分配的内存(可能由malloc(3)分配给其他方式,这对您的程序来说是灾难性的事情)

你知道,free(ptr)不能使指针ptr变成NULL,因为每个参数在c中都是按值传递的,所以free(ptr);后面跟着ptr = NULL;是一个很好的选择。

顺便说一句,有一个最小的,可复制的例子可以很好地搜索任何其他可能的错误。

最新更新