- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在使用 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/
创建一个“海盗对话”,可以选择左手或右手。我希望它对“左”和“右”的不同拼写做出积极的回答(正如您将在代码中看到的那样),但是,当我为所有非“右”或“左”的输入添加最终的“else”代码时,它给了我一
With 语句 对一个对象执行一系列的语句。 With object statements End With 参数 object 必需的部分
While...Wend 语句 当指定的条件为 True 时,执行一系列的语句。 While condition  ; Version [stat
所以我正在处理的代码有一个小问题。 while True: r = input("Line: ") n = r.split() if r == " ":
我有一个对象数组: var contacts = [ { "firstName": "Akira", "lastName": "Laine", "number"
int main() { int f=fun(); ... } int fun() { return 1; return 2; } 在上面的程序中,当从main函数中调用一个
我的项目中有很多 if 语句、嵌套 if 语句和 if-else 语句,我正在考虑将它们更改为 switch 语句。其中一些将具有嵌套的 switch 语句。我知道就编译而言,switch 语句通常更
Rem 语句 包含程序中的解释性注释。 Rem comment 或 ' comment comment 参数是需要包含的注释文本。在 Rem 关键字和 comment 之间应有一个空格。
ReDim 语句 在过程级中声明动态数组变量并分配或重新分配存储空间。 ReDim [Preserve] varname(subscripts) [, varname(subscripts)]
Randomize 语句 初始化随机数生成器。 Randomize [number] number 参数可以是任何有效的数值表达式。 说明 Randomize 使用 number 参数初始
Public 语句 定义公有变量并分配存储空间。在 Class 块中定义私有变量。 Public varname[([subscripts])][, varname[([subscripts])
Sub 语句 声明 Sub 过程的名称、参数以及构成其主体的代码。 [Public [Default]| Private] Sub name [( arglist )]
Set 语句 将对象引用赋给一个variable或property,或者将对象引用与事件关联。 Set objectvar = {objectexpression | New classname
我有这个代码块,有时第一个 if 语句先运行,有时第二个 if 语句先运行。我不确定为什么会这样,因为我认为 javascript 是同步的。 for (let i = 0; i < dataObje
这是一个 javascript 代码,我想把它写成这样:如果此人回答是,则回复“那很酷”,如果此人回答否,则回复“我会让你开心”,如果此人回答的问题包含"is"或“否”,请说“仅键入”是或否,没有任何
这是我的任务,我尝试仅使用简短的 if 语句来完成此任务,我得到的唯一错误是使用“(0.5<=ratio<2 )”,除此之外,构造正确吗? Scanner scn = new Scanner(
有没有办法在 select 语句中使用 if 语句? 我不能在这个中使用 Case 语句。实际上我正在使用 iReport 并且我有一个参数。我想要做的是,如果用户没有输入某个参数,它将选择所有实例。
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: If vs. Switch Speed 我将以 C++ 为例,但我要问的问题不是针对特定语言的。我的意思是一
Property Set 语句 在 Class 块中,声明名称、参数和代码,这些构成了将引用设置到对象的 Property 过程的主体。 [Public | Private] Pro
Property Let 语句 在 Class 块中,声明名称、参数和代码等,它们构成了赋值(设置)的 Property 过程的主体。 [Public | Private] Prop
我是一名优秀的程序员,十分优秀!