- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试在不使用系统调用且不使用大量库的情况下删除一个非空目录。到目前为止我的代码是...
int rmrf(char *path) {
char* path_copy = (char *) malloc(1024 * sizeof(char));
strcpy(path_copy, path);
DIR *directory = opendir(path_copy);
struct dirent *entry = readdir(directory);
while (entry != NULL) {
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { //skip /. and /..
} else if (entry->d_type == DT_DIR) { //directory recurse
strcat(path_copy, "/");
strcat(path_copy, entry->d_name);
rmrf(path_copy);
remove(path);
} else { //file delete
strcat(path_copy, "/");
strcat(path_copy, entry->d_name);
remove(path_copy);
}
entry = readdir(directory);
}
closedir(directory);
return 0;
}
我当前的文件结构看起来像这样......
Who
|---Region 1
|---County 1
|---SubCounty 1
|---County 2
|---Region 2
|---County 1
|---Region 3
目前我遇到段错误,但随着时间的推移出现在不同的地方。今天早些时候,我将深入了解两层递归,然后将错误排除在外,但截至目前,我什至无法通过一个完整的层级。我不知道出了什么问题,当我使用 gdb 调查问题时,我得到...
malloc.c: No such file or directory.
如有任何帮助,我们将不胜感激!
更新:
我采纳了 paxdiablo 的建议并提出了结果函数...
int rmrf(char *path) {
char* path_copy = malloc(1024);
DIR *directory = opendir(path);
struct dirent *entry = readdir(directory);
while (entry != NULL) {
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { //skip /. and /..
} else if (entry->d_type == DT_DIR) { //directory recurse
strcpy(path_copy, path);
strcat(path_copy, "/");
strcat(path_copy, entry->d_name);
rmrf(path_copy);
remove(path);
} else { //file delete
strcpy(path_copy, path);
strcat(path_copy, "/");
strcat(path_copy, entry->d_name);
remove(path_copy);
}
entry = readdir(directory);
}
closedir(directory);
free(path_copy);
return 0;
}
但是我仍然遇到段错误,尽管它在递归中越来越远。段错误的 gdb 输出如下...
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=av@entry=0x7ffff7dd1b20 <main_arena>, bytes=bytes@entry=32816) at malloc.c:3802
3802 malloc.c: No such file or directory.
(gdb) where
#0 _int_malloc (av=av@entry=0x7ffff7dd1b20 <main_arena>, bytes=bytes@entry=32816) at malloc.c:3802
#1 0x00007ffff7a91184 in __GI___libc_malloc (bytes=32816) at malloc.c:2913
#2 0x00007ffff7ad51ba in __alloc_dir (statp=0x7fffffffe190, flags=0, close_fd=true, fd=6) at ../sysdeps/posix/opendir.c:247
#3 opendir_tail (fd=6) at ../sysdeps/posix/opendir.c:145
#4 __opendir (name=<optimized out>) at ../sysdeps/posix/opendir.c:200
#5 0x0000000000401bca in rmrf ()
#6 0x0000000000401c8d in rmrf ()
#7 0x0000000000401c8d in rmrf ()
#8 0x0000000000402380 in main ()
想法?
最佳答案
对于您的初始代码,您在进入函数时执行此操作一次:
strcpy(path_copy, path);
然后对当前目录中的每个 文件或目录执行此操作:
strcat(path_copy, "/");
strcat(path_copy, entry->d_name);
这意味着,如果您的当前目录 /xx
中有文件 a
、b
和 c
, path_copy
变量将循环通过:
/xx/a /xx/a/b /xx/a/b/c
而不是正确的:
/xx/a /xx/b /xx/c
如果文件数量足够大,您将很容易耗尽为路径分配的 1024 字节。
如果你想解决这个问题,那么你应该每次都从头开始这个变量:
if ((strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0)) {
if (entry->d_type == DT_DIR) {
strcpy(path_copy, path);
strcat(path_copy, "/");
strcat(path_copy, entry->d_name);
rmrf(path_copy);
remove(path);
} else {
sprintf(path_copy, "%s/%s", path, entry->d_name);
remove(path_copy);
}
}
您会注意到我已经稍微修改了您的初始条件以使其更有意义(仅当文件既不是 .
也不是 ..
).
我还在 else
子句中展示了使用 sprintf
而不是一组 strcpy/strcat 来构造要删除的字符串的更短方法
调用。如果您愿意,也可以在 if
子句中随意执行此操作,我使用旧方法保留它,因此您可以看到您需要做的就是添加初始路径。
还有一些额外的要点,适用于您的第一个和/或第二个代码片段:
您还应该确保在 closedir()
和 之间,释放您在每个级别分配的内存,紧接在从函数返回之前返回
。
您从不需要转换 malloc
的返回值,因为 void *
可以隐式转换为任何其他类型的指针。事实上,这样做很危险,因为它可以隐藏某些细微的错误。
同样,您永远不需要乘以 sizeof(char)
- 也就是说,根据定义,总是乘以 1。
您可以将 path_copy
的创建移动到文件/目录检查之前,因为它对这两个部分都是通用的。
最后,如果您正在处理的目录实际上不存在,您将遇到麻烦,因为 opendir
将返回 NULL,您将立即尝试将其传递给readdir
.
考虑到所有这些,我将从以下程序开始,该程序实际上遍历 树并打印出它找到的所有文件。对此感到满意后,您可以添加回删除的位:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int rmrf(char *path) {
char *path_copy = malloc(1024);
DIR *directory = opendir(path);
if (directory != NULL) {
struct dirent *entry = readdir(directory);
while (entry != NULL) {
if ((strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0)) {
sprintf(path_copy, "%s/%s", path, entry->d_name);
if (entry->d_type == DT_DIR) {
rmrf(path_copy);
puts(path);
} else {
puts(path_copy);
}
}
entry = readdir(directory);
}
closedir(directory);
}
free(path_copy);
return 0;
}
主要代码只是一个驱动程序,以确保正确设置思想。只需确保在运行之前,您没有(在当前目录中)要保留的 paxtest
或 paxtest2
文件或目录。
int main(void) {
system("rm -rf paxjunk");
system("mkdir paxjunk");
system("touch paxjunk/0.txt");
system("mkdir paxjunk/1");
system("touch paxjunk/1/1.txt");
system("mkdir paxjunk/2");
system("touch paxjunk/2/2.txt");
rmrf("paxjunk");
puts("===");
system("rm -rf paxjunk2");
rmrf("paxjunk2");
puts("===");
system("rm -rf paxjunk");
return 0;
}
当你运行它时,你应该看到它工作正常:
paxjunk/0.txt
paxjunk/1/1.txt
paxjunk
paxjunk/2/2.txt
paxjunk
===
===
关于c - 使用C删除非空目录时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49746934/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!