我正在尝试创建一个程序,该程序创建一个目录,其中创建了多个目录,然后在每个目录中创建一个文件。我似乎无法打开那些"多个目录"。这样我可以把我的文件。我试着使用name3
作为参数,我也试着用name3的值创建一个const char*,没有任何工作。
error: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. Aborted (core dumped)
这是我的代码
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
int make_directory(char * name) {
int checker=mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO);
return checker;
}
char** getNames() {
char** names=malloc(10*sizeof(char*));
for(int i=0;i<10;i++) {
if(i==9) {
names[i]=malloc(3*sizeof(char));
names[i][0]='1';
names[i][1]='0';
names[i][2]=' ';
} else {
names[i]=malloc(2*sizeof(char));
names[i][0]=49+i;
names[i][1]=' ';
}
}
return names;
}
int makeTenDirs() {
char **names=getNames();
char *name2;
for(int i=0;i<10;i++) {
name2=NULL;
name2=getcwd(NULL,0);
strncat(name2,"/input/dir",11);
strncat(name2,names[i],1);
int s=make_directory(name2);
}
name2=NULL;
name2=getcwd(NULL,0);
strncat(name2,"/input/dir",11);
strncat(name2,names[0],1);
strncat(name2,"0",2);
int s=make_directory(name2);
}
int main() {
char **names=getNames();
FILE *file;
DIR *dir;
DIR *dir2;
struct dirent *dent;
char * name1="./input";
char *name3;
int proceed=make_directory("./input");
if(proceed==-1) {
printf("Error making the directoryn");
}
makeTenDirs();
dir=opendir("./input");
if(dir!=NULL) {
name3=getcwd(NULL,0);
while((dent=readdir(dir))!=NULL){
if(strcmp(dent->d_name,"..")!=0 && strcmp(dent->d_name,".")!=0) {
name3=getcwd(NULL,0);
strncat(name3,"/input/",8);
strncat(name3,dent->d_name,10);
printf("%sn",name3);
dir2=opendir(name3);
if(dir2!=NULL) {
printf("alo");
}
}
}
}
closedir(dir);
free(names);
return 0;
}
关于如何打开目录(也许把文件放在其中)有什么建议吗?
下面是一个工作实现。我清理了所有的警告(你有一些未使用的变量,makeTenDirs
没有返回值)。总是查看并修复警告,使用-Wall -Wextra
标志来启用它们。正如我之前所想的那样,您通过覆盖name2
和name3
的缓冲区来调用未定义的行为。您使用getcwd
的方式为name2
和name3
分配了足够的空间。只要您将strcat
设置为该值,就会覆盖缓冲区,从而调用UB。在这一点上,程序可以以完全不可预测的方式运行,包括看起来工作。你希望你的程序在有UB的时候崩溃,这样你就能注意到这个问题。下面,我使用了getcwd
的第二种操作模式,它内部没有malloc
内存,而是将所有内容保存在自动内存中(在堆栈上)。这使您不必手动管理内存。我已经包含了评论,希望能解释所有的问题,如果你有问题,请告诉我。
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <linux/limits.h> // for PATH_MAX
int make_directory(char * name) {
int checker=mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO);
return checker;
}
char** getNames() {
char** names=malloc(10*sizeof(char*));
for(int i=0;i<10;i++) {
if(i==9) {
names[i]=malloc(3*sizeof(char));
names[i][0]='1';
names[i][1]='0';
names[i][2]=' ';
} else {
names[i]=malloc(2*sizeof(char));
names[i][0]='1'+i;
names[i][1]=' ';
}
}
return names;
}
int makeTenDirs(char** names) {
// This is where your problems began. As I suggested before and confirmed
// when I actually ran the code, `getcwd(NULL, 0)` returns a pointer to
// dynamically allocated memory that's just big enough to hold the path.
// As soon as you strcat to that, you overflow the buffer causing
// undefined behavior. It crashed for me 2nd time through the loop, not
// immediately when the UB occurred. Your results could be entirely different,
// that is the essence of UB. To fix it, I will declare an automatic array
// of PATH_MAX large (4096 I believe). That should make this fixed size array
// able to handle any path on your _linux_ box (this code will not be portable
// to windows). Alternatively, you could do what you did before, just be sure
// to realloc the name2 memory _before_ strcat'ing so there's enough room for
// "/input/dir"
char name2[PATH_MAX];
// only acceptable place for one character variable names are loop index
// variables, and you'll even get some argument on that. Give your variables
// descriptive names (although, I'd probably just make this function void, not
// much utility in the return value here, which you didn't even return!)
int directoryMade = 0;
for(int i=0;i<10;i++) {
// This returns NULL if the `sizeof name` (==PATH_MAX == 4096) is too
// small to hold the path. That shouldn't be the case since no paths
// on the system should exceed PATH_MAX, but it's always a good idea
// to check for errors, that's what a lot of your C code should be
// doing, so get in the habit. Also, realize your old way created
// a memory leak each time since each call to getcwd would malloc more
// memory, and you overwrite the pointer to the previous block with the
// pointer to the new block. Now nothing is pointing at the previous
// block so you can't free it --> memory leak.
if (getcwd(name2, sizeof name2) == NULL)
{
perror("Path exceeded buffer length");
exit(-1);
}
// should be plenty of space to strcat now
strncat(name2,"/input/dir",11);
strncat(name2,names[i],1);
// not much utility b/c it keeps getting overwritten. You could check it each time
// and return if there's an error
directoryMade=make_directory(name2);
}
if (getcwd(name2, sizeof name2) == NULL)
{
perror("Path exceeded buffer length");
exit(-1);
}
strncat(name2,"/input/dir",11);
strncat(name2,names[0],1);
strncat(name2,"0",2);
directoryMade=make_directory(name2);
return directoryMade;
}
int main() {
char **names=getNames();
DIR *dir;
DIR *dir2;
struct dirent *dent;
int proceed=make_directory("./input");
if(proceed==-1) {
// you print an error here, but continue on anyway
// as if there was no error
printf("Error making the directoryn");
}
makeTenDirs(names); // you already fetched names, use them!
dir=opendir("./input");
if(dir!=NULL) {
// same problem here. name3 holds _exactly_ how much space it
// needs when you allow getcwd to malloc memory for it. As before,
// you can make name3 an array in automatic storage, or realloc it
// before strcat'ing
char name3[PATH_MAX];
// check for NULL return here too. Not showing it because I'm getting lazy
getcwd(name3, sizeof name3);
while((dent=readdir(dir))!=NULL){
if(strcmp(dent->d_name,"..")!=0 && strcmp(dent->d_name,".")!=0) {
// check for NULL return
getcwd(name3, sizeof name3);
strncat(name3,"/input/",8);
strncat(name3,dent->d_name,10);
printf("%sn",name3);
dir2=opendir(name3);
if(dir2!=NULL) {
// printf is line-buffered, so this won't print right away unless
// you put a newline on it (or fflush(stdout);)
printf("alon");
// close this dir too?
closedir(dir2);
}
}
}
}
closedir(dir);
// this is NOT a complete free. You have a double pointer. You need to loop and
// free each of names[0], names[1], .. names[9], _then_ free(names). I'll leave
// that as an exercise. In general, you should have a matching number of malloc's
// and free's.
free(names);
return 0;
}