gpt4 book ai didi

c - if 语句中的 malloc(),仅当输入 (if) 时才分配,但 valgrind 表示字节丢失

转载 作者:行者123 更新时间:2023-11-30 18:44:14 25 4
gpt4 key购买 nike

在使用 C 的作业上下文中,我必须创建一个 li 克隆,我试图访问目录中的所有子文件的名称。

根据大众的要求,这里是重现此问题的最少代码(请考虑删除您的反对票...)(当我说它很多时,我不是在开玩笑)。

首先,将此文件结构放在某处(.txt 文件具有键盘杂耍):

var
├── file1.txt
└── var2
├── test -> ../../test
├── var3
│   ├── file2.txt
│   └── file3.txt
└── varfind -> ../

4 directories, 3 files

要重现的代码main.c

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

#include "helpers.h"

int main(int argc, char **argv) {
char *destination = malloc(sizeof(char[THEORETICAL_MAX_PATH_LENGTH]));
switch (argc) {
case 1: // (== Error case)
fprintf(stderr, "Usage: %s file\n", argv[0]);
exit(EXIT_FAILURE);
break;
case 2: // (== List)
stripSlash(argv[argc - 1], destination);
Object* obj = createNode(destination, NULL);
freeNode(obj);
break;
default:
exit(0);
break;
}
free(destination);
}

helpers.h

#ifndef HEADER_UTILITIES
#define HEADER_UTILITIES
#define THEORETICAL_MAX_PATH_LENGTH 4096

#include <sys/stat.h>

typedef struct {
int numberOfChildren;
char path[2][THEORETICAL_MAX_PATH_LENGTH];
struct stat info;
struct Object **children; // child[0] is parent.
} Object;

void stripSlash(char arg[], char *filename);

void freeNode(Object *node);
Object * createNode(const char *filename, Object *parent);

#endif

helpers.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <dirent.h>
#include "helpers.h"

void stripSlash(char arg[], char *filename) {
strncpy(filename, arg, THEORETICAL_MAX_PATH_LENGTH);
if (filename[strlen(filename) - 1] == '/')
filename[strlen(filename) - 1] = '\0';
}

void getChildren(const char *path, struct stat* statBuffer, char *files[THEORETICAL_MAX_PATH_LENGTH], int *numberOfFiles) {
int count = 0;
struct dirent *currentDir;
if (lstat(path, statBuffer) == 0 && S_ISDIR(statBuffer->st_mode)) {
DIR *folder = opendir(path);
if (access(path, F_OK) != -1) {
if (folder)
while ((currentDir = readdir(folder))) {
if (strcmp(currentDir->d_name, ".") && strcmp(currentDir->d_name, "..")) {
files[count] = (char*) malloc(THEORETICAL_MAX_PATH_LENGTH);
snprintf(files[count], THEORETICAL_MAX_PATH_LENGTH, "%s", currentDir->d_name);
count++;
}
}
free(currentDir);
}
closedir(folder);
} else if (errno < 0)
printf("ERROR %d\n", errno);

*numberOfFiles = count;
}

int rippleCycleCheckUpwards(Object *parent, __ino_t inode) {
if (parent)
if (parent->info.st_ino == inode)
return 1;
else
return rippleCycleCheckUpwards((Object*) parent->children[0], inode);
else
return 0;
}

void freeNode(Object *node) {
node->children[0] = NULL;
for (int i = 1; i < node->numberOfChildren + 1; i++)
freeNode((Object*) node->children[i]);
free(node->children[0]);
free(node->children);
free(node);
node = NULL;
}

Object * createNode(const char *filename, Object *parent) {
Object *node = malloc(sizeof(Object));

char *files[THEORETICAL_MAX_PATH_LENGTH];
char *realDestination = malloc(THEORETICAL_MAX_PATH_LENGTH);
char *res = realpath(filename, realDestination);

strncpy(node->path[0], filename, THEORETICAL_MAX_PATH_LENGTH - 1);
if (res) {
strncpy(node->path[1], realDestination, THEORETICAL_MAX_PATH_LENGTH - 1);
strncat(node->path[1], "\0", 1);
}
free(realDestination);

struct stat *info = malloc(sizeof(struct stat));
lstat(filename, info);
if (S_ISLNK(info->st_mode) == 1) {
getChildren(node->path[1], &node->info, files, &node->numberOfChildren);
} else {
getChildren(node->path[0], &node->info, files, &node->numberOfChildren);
}
free(info);

node->children = malloc((1 + node->numberOfChildren) * sizeof(Object*));
node->children[0] = (struct Object*) parent;

if (rippleCycleCheckUpwards((Object*) parent, node->info.st_ino) == 1) {
node->numberOfChildren = 0;
}

for (int i = 0; i < node->numberOfChildren; i++) {
char nextfile[THEORETICAL_MAX_PATH_LENGTH];
snprintf(nextfile, THEORETICAL_MAX_PATH_LENGTH - 1, "%s/%s", filename, files[i]);

if (S_ISDIR(node->info.st_mode) || S_ISLNK(node->info.st_mode)) {
node->children[i + 1] = (struct Object*) createNode(nextfile, node);
}
free(files[i]);
}
return node;
}

您可以使用此 Makefile 或 gcc 进行构建:

CC=gcc
CCFLAGS=-Wall -g
LDFLAGS=
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.c=.o)
TARGET=ultra_cp

all: $(TARGET)

$(TARGET): $(OBJECTS)
$(CC) -o $@ $^ $(LDFLAGS)

%.o: %.c %.h
$(CC) $(CCFLAGS) -c $<

%.o: %.c
$(CC) $(CCFLAGS) -c $<

clean:
rm -f *.o $(TARGET)

然后使用 make 进行测试,然后使用 ./ultra_cp var 进行标准使用或

valgrind --tool=memcheck --leak-check=yes --track-origins=yes --read-var-info=yes ./ultra_cp var

我的问题是 valgrind 打印出来:

HEAP SUMMARY:
==3221== in use at exit: 8,192 bytes in 2 blocks
==3221== total heap usage: 112 allocs, 110 frees, 670,440 bytes allocated
==3221==
==3221== 8,192 bytes in 2 blocks are definitely lost in loss record 1 of 1
==3221== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3221== by 0x108CA1: getChildren (helpers.c:29)
==3221== by 0x108F86: createNode (helpers.c:80)
==3221== by 0x1090F8: createNode (helpers.c:98)
==3221== by 0x1090F8: createNode (helpers.c:98)
==3221== by 0x1091E3: main (main.c:15)
==3221==
==3221== LEAK SUMMARY:
==3221== definitely lost: 8,192 bytes in 2 blocks
==3221== indirectly lost: 0 bytes in 0 blocks
==3221== possibly lost: 0 bytes in 0 blocks
==3221== still reachable: 0 bytes in 0 blocks
==3221== suppressed: 0 bytes in 0 blocks

helpers.c:29 是调用 files[count] = (char*) malloc(THEORETICAL_MAX_PATH_LENGTH); 的行以及它执行的情况数不在 if 语句中输入。

它不会妨碍我的代码的功能,但我希望尽可能避免内存泄漏,并随后感谢您在此事上提供的任何帮助。

编辑

感谢用户dbush谁提供了问题的根源,因为在调用rippleCycleCheckUpwards(...)的非常具体的情况下,我不会清空files的子项。

helpers.c 中可以替换

    if (rippleCycleCheckUpwards((Object*) parent, node->info.st_ino) == 1) {
node->numberOfChildren = 0;
}

    if (rippleCycleCheckUpwards((Object*) parent, node->info.st_ino) == 1) {
for (int i = 0; i < node->numberOfChildren; i++) {
free(files[i]);
}
node->numberOfChildren = 0;
}

最佳答案

如果您有条件地分配内存,则还必须释放它。直觉上,人们可能会认为他们需要在尝试释放内存之前检查内存是否已分配,但幸运的是,C 标准已经涵盖了我们。

您可以通过在循环外部(或在 else 语句中)将文件指针设置为 NULL,然后调用 free 来绕过某些代码。 () 稍后在代码中,一旦您知道您将不再使用内存。您不需要检查指针是否已分配,因为 free(NULL) is a perfectly legal no-op.

关于c - if 语句中的 malloc(),仅当输入 (if) 时才分配,但 valgrind 表示字节丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58630535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com