【发布时间】:2020-07-09 19:33:52
【问题描述】:
现在我正在学习 C,但我在内存分配方面遇到了问题,至少我从我的代码错误中了解到这一点。
代码
#ifndef __FILE_H__
#define __FILE_H__
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct Files Files;
typedef struct DirList DirList;
typedef struct NodeFile NodeFile;
typedef struct NodeDir NodeDir;
typedef struct Directory {
// The name of the directory
char *name;
// TODO: The list of files of the current directory
Files *files;
// TODO: The list of dirs of the current directory
DirList *dirs;
// The parent directory of the current directory (NULL for the root
// directory)
struct Directory *parentDir;
} Directory;
// DO NOT MODIFY THIS STRUCTURE
typedef struct File {
// The name of the file
char *name;
// The size of the file
int size;
// The content of the file
char *data;
// The directory in which the file is located
Directory *dir;
} File;
typedef struct Files {
NodeFile *first;
NodeFile *last;
} Files;
typedef struct DirList {
NodeDir *first;
NodeDir *last;
} DirList;
typedef struct NodeFile {
struct NodeFile *next;
struct NodeFile *prev;
File *newfile;
} NodeFile;
typedef struct NodeDir {
struct NodeDir *next;
struct NodeDir *prev;
Directory *newdir;
} NodeDir;
// create root of file system
void makeroot(Directory **root)
{
*root = (Directory *) malloc(sizeof(Directory));
(*root)->parentDir = NULL;
(*root)->name = strdup("/");
(*root)->files = NULL;
(*root)->dirs = NULL;
}
// remove root of file system
void deleteroot(Directory *root)
{
root = NULL;
free(root);
}
//add new file to current directory
File *touch(Directory *root, char *nume, char *content)
{
NodeFile *new = (NodeFile *) malloc(sizeof(NodeFile));
new->newfile = (File *) malloc(sizeof(File));
new->newfile->name = (char *) malloc(strlen(nume) + 1);
new->newfile->data = (char *) malloc(strlen(content) + 1);
strcpy(new->newfile->name, nume);
strcpy(new->newfile->data, content);
if (root->files == NULL) {
root->files = (Files *) malloc(sizeof(Files));
root->files->first = (NodeFile *) malloc(sizeof(NodeFile));
root->files->last = (NodeFile *) malloc(sizeof(NodeFile));
//if no file in folder root has first and last position
root->files->first = new;
root->files->last = new;
} else if (strcmp(root->files->first->newfile->name,
new->newfile->name) > 0) {
new->next = root->files->first;
root->files->first = new;
} else if (strcmp(root->files->last->newfile->name,
new->newfile->name) < 0) {
root->files->last->next = new;
root->files->last = new;
} else {
NodeFile *i = root->files->first;
while (i != root->files->last) {
if (strcmp(i->next->newfile->name,
new->newfile->name) > 0) {
if (i == root->files->first->next)
i = root->files->first;
i->next->prev = new;
new->next = i->next;
new->prev = i;
i->next = new;
break;
}
i = i->next;
}
}
return new->newfile;
}
// Create directory
Directory *mkdir(Directory *parent, char *name)
{
NodeDir *new = (NodeDir *) malloc(sizeof(NodeDir));
//new->newdir = (Directory *) malloc(sizeof(Directory));
new->newdir = (Directory *) malloc(strlen(Directory) + 1);
new->newdir->name = (char *) malloc(strlen(name) + 1);
strcpy(new->newdir->name, name);
new->newdir->parentDir = parent;
if (parent->dirs == NULL) {
parent->dirs = (DirList *)malloc(sizeof(DirList));
parent->dirs->first = (NodeDir *) malloc(sizeof(NodeDir));
parent->dirs->last = (NodeDir *) malloc(sizeof(NodeDir));
parent->dirs->first = new;
parent->dirs->last = new;
} else if (strcmp(parent->dirs->first->newdir->name,
new->newdir->name) > 0) {
new->next = parent->dirs->first;
parent->dirs->first = new;
} else if (strcmp(parent->dirs->last->newdir->name,
new->newdir->name) < 0) {
parent->dirs->last->next = new;
parent->dirs->last = new;
} else {
NodeDir *i = parent->dirs->first->next;
while (i != NULL) {
if (strcmp(i->newdir->name, new->newdir->name) > 0) {
if (i == parent->dirs->first->next)
i = parent->dirs->first;
i->next->prev = new;
new->next = i->next;
new->prev = i;
i->next = new;
break;
}
i = i->next;
}
}
return new->newdir;
}
// traverse list and print files and folders names
void ls(Directory *parent)
{
if (parent->files != NULL) {
NodeFile *i;
for (i = parent->files->first; i != NULL; i = i->next)
printf("%s ", i->newfile->name);
}
if (parent->dirs != NULL) {
NodeDir *j;
for (j = parent->dirs->first; j != NULL; j = j->next)
printf("%s ", j->newdir->name);
}
printf("\n");
}
// working directory
void pwd(Directory *dir)
{
if (dir->parentDir == NULL)
return;
if (dir->parentDir != NULL) {
pwd(dir->parentDir);
printf("/%s", dir->name);
}
}
Directory *cd(Directory *dir, char *where)
{
if (strcmp(where, "..") == 0 && dir->parentDir != NULL) {
return dir->parentDir;
} else if (dir->dirs == NULL)
printf("Cannot move to ‘%s’: No such directory!\n", where);
else {
NodeDir *it = dir->dirs->first;
while (it != NULL) {
if (strcmp(it->newdir->name, where) == 0) {
dir = it->newdir;
break;
}
it = it->next;
}
if (it == NULL)
printf("Cannot move to ‘%s’: No such directory!\n",
where);
free(it);
}
return dir;
}
void tree(Directory *parent, int i)
{
if (i == 1)
printf("\n%s\n", parent->name);
if (parent->files != NULL) {
NodeFile *it;
for (it = parent->files->first; it != NULL; it = it->next) {
if (i != 1) {
int j;
for (j = 0; j < i; j++)
printf(" ");
}
printf(" %s\n", it->newfile->name);
}
free(it);
}
if (parent->dirs != NULL) {
NodeDir *it = parent->dirs->first;
while (it != NULL) {
int j;
for (j = 0; j < i; j++)
printf(" ");
printf("%s\n", it->newdir->name);
i = i + 1;
tree(it->newdir, i);
it = it->next;
i = i - 1;
}
free(it);
}
}
void rm(Directory *parent, char *dirname)
{ //it -- item
NodeFile *it;
for (it = parent->files->first; it != NULL; it = it->next) {
if (strcmp(it->newfile->name, dirname) == 0) {
if (it == parent->files->first) {
parent->files->first =
parent->files->first->next;
} else if (it == parent->files->last) {
parent->files->last = it->prev;
} else {
it->prev->next = it->next;
it->next->prev = it->prev;
}
it = NULL;
free(it);
return;
}
}
if (it == NULL) {
printf("Cannot remove ‘%s’: No such file!\n", dirname);
free(it);
}
}
void rmdir(Directory *parent, char *dirname)
{
NodeDir *it;
for (it = parent->dirs->first; it != NULL; it = it->next) {
if (strcmp(it->newdir->name, dirname) == 0) {
if (it == parent->dirs->first) {
parent->dirs->first =
parent->dirs->first->next;
} else if (it == parent->dirs->last) {
parent->dirs->last =
parent->dirs->last->prev;
} else {
it->prev->next = it->next;
it->next->prev = it->prev;
}
it = NULL;
free(it);
return;
}
}
if (it == NULL) {
printf("Cannot remove ‘%s’: No such directory!\n", dirname);
free(it);
}
}
#endif
/* __FILE_H__ */
Valgrind 输出:
> create fs ls
>
> ls
>
> mkdir test ls
> ==11466== Conditional jump or move depends on uninitialised value(s)
> ==11466== at 0x109025: ls (file.h:189)
> ==11466== by 0x1097D4: main (main.c:86)
> ==11466== Uninitialised value was created by a heap allocation
> ==11466== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==11466== by 0x108D44: mkdir (file.h:134)
> ==11466== by 0x109766: main (main.c:81)
【问题讨论】:
-
#ifndef __FILE_H__?以双下划线开头的标识符,以及以单下划线和大写字母开头的标识符是保留的,不应使用。 7.1.3 Reserved identifiers: "所有以下划线和大写字母或另一个下划线开头的标识符始终保留供任何使用。"
标签: c memory heap-memory