Valgrind 打印函数中出现奇怪的内存泄漏

问题描述 投票:0回答:1

这是一个用于管理停车场的 C 脚本,我有这个结构:

typedef struct {
    char name[MAXSIZE];
    int capacity;
    char car_plates[MAXREGISTRATIONS][PLATE_SIZE];
    char entry_dates[MAXREGISTRATIONS][DATE_SIZE];
    char entry_hours[MAXREGISTRATIONS][HOUR_SIZE];
    char exit_date[DATE_SIZE]; 
    char exit_hour[HOUR_SIZE];
    float value_15_minutes;
    float value_after_1_hour;
    float max_daily_value;
    float revenue;
    int available_spaces;
} ParkingLot;
int num_parks = 0;
ParkingLot parks[MAXPARKS];

我有一个名为“创建公园”的功能,效果很好:

void createParking(char name[], int capacity, float value_15_minutes, float value_after_1_hour, float max_daily_value) {
    if (num_parks >= MAXPARKS) {
        printf("Too many parks.\n");
        return;
    }
    
    for (int i = 0; i < num_parks; i++) {
        if (strcmp(parks[i].name, name) == 0) {
            printf("%s: Parking already exists.\n", name);
            return;
        }
    }
    if(capacity <= 0){
        printf("%d: Invalid capacity.\n", capacity);
        return;
    }
    if (value_15_minutes <= 0 || value_after_1_hour <= value_15_minutes || max_daily_value <= value_after_1_hour) {
        printf("Invalid cost.\n");
        return;
    }

    strcpy(parks[num_parks].name, name);
    parks[num_parks].capacity = capacity;
    parks[num_parks].value_15_minutes = value_15_minutes;
    parks[num_parks].value_after_1_hour = value_after_1_hour;
    parks[num_parks].max_daily_value = max_daily_value;
    parks[num_parks].available_spaces = capacity;


    num_parks++;
}

所以这只是为了上下文,该函数不是问题,问题是我的代码中出现内存泄漏,考虑到我有零个 malloc,我认为这很奇怪。这是 Valgrind 报告,以及所有函数已发行

==3537366== 4,096 bytes in 1 block are still reachable in loss record 32 of 32
==3537366==    at 0x4843828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3537366==    by 0x48D6633: _IO_file_doallocate (filedoalloc.c:101)
==3537366==    by 0x48E65AF: _IO_doallocbuf (genops.c:347)
==3537366==    by 0x48E550F: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:744)
==3537366==    by 0x48E3CE4: _IO_new_file_xsputn (fileops.c:1243)
==3537366==    by 0x48E3CE4: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1196)
==3537366==    by 0x48B4AA0: __printf_buffer_flush_to_file (printf_buffer_to_file.c:59)
==3537366==    by 0x48B4AA0: __printf_buffer_to_file_done (printf_buffer_to_file.c:120)
==3537366==    by 0x48BEB48: __vfprintf_internal (vfprintf-internal.c:1460)
==3537366==    by 0x498B63A: __printf_chk (printf_chk.c:33)
==3537366==    by 0x10C6F8: printf (stdio2.h:86)
==3537366==    by 0x10C6F8: list_parks (project.c:429)
==3537366==    by 0x10C6F8: command_p (project.c:978)
==3537366==    by 0x109377: main (project.c:1275)

int main() {
   
    
    while (1) {
        char command[50];
        scanf("%s", command);
        if (strcmp(command, "q") == 0) {
            release_daily_revenue(&daily_revenue);
            
            break;
        }
        check_input(command);
    }
    
    return 0;
}

void command_p(char command[]) {
    int rc;
    char name[MAXSIZE];
    float capacity;
    float value_15, value_15_after_1_hour, max_daily_value;

    if (strcmp(command, "p") == 0) {
        char nextChar = getchar();
        if (nextChar == '\n') {
            list_parks();
        } else {
            ungetc(nextChar, stdin);
            char str[MAXSIZE * 5]; // Increasing the size to handle complete input
            if (fgets(str, MAXSIZE * 5, stdin) == NULL) {
                return;
            }
            
            if ((rc = sscanf(str, "%s %f %f %f %f", name, &capacity, &value_15, &value_15_after_1_hour, &max_daily_value)) != 5) {
                rc = sscanf(str, " \"%[^\"]\" %f %f %f %f", name, &capacity, &value_15, &value_15_after_1_hour, &max_daily_value);
            
           
            createParking(name, (int)capacity, value_15, value_15_after_1_hour, max_daily_value);
        }
    }
}

void list_parks() {
    for (int i = 0; i < num_parks; i++) {
        printf("%s %d %d\n", parks[i].name, parks[i].capacity, parks[i].available_spaces);
    }
    return;
}

valgrind 报告说我在 list_parks 函数中的 1 个块中丢失了 4096 个字节,我无法理解这是如何发生的,并且另外丢失了 4096 个字节(仍然可达),总共 164 个块中的 10,553 个字节(一些其余代码中的其他小泄漏)。你能帮我弄清楚这里到底发生了什么吗

c memory valgrind
1个回答
0
投票

鉴于最近 liblzma 的崩溃,不要急于听人们说问题是误报。

“最小可重现示例”也不能替代了解 Valgrind 的工作原理。

评论是正确的,这是 GNU libc 为 I/O 缓冲完成的一次性分配。由于某种原因(也许您使用的 Valgrind 版本太旧),Valgrind 没有运行 glibc 清理功能。您的 glibc 也可能存在缺陷,并且它没有使用 __libc_freeres 释放内存。

如果你运行

valgrind -v -v [your exe]
你应该看到类似的东西

--16708-- Caught __NR_exit; running __gnu_cxx::__freeres and __libc_freeres() wrapper

如果没有您的操作系统、编译器和 Valgrind 版本的更多详细信息,我无法说出原因

© www.soinside.com 2019 - 2024. All rights reserved.