双链接结构列表的内存泄漏
Memory leak of doubly linked struct list
我正在使用c 的Ubuntu 16.04 Linux的文件crawler工作。
文件crawler是我对书Modern Operating Systems by Andrew Tanenbaum 4th edition
的问题的解决方案,如下所示:
编写一个从给定目录开始的程序,然后从中降下文件树 点记录其找到的所有文件的大小。全部完成后,它应该打印 使用指定为参数的箱宽度的文件大小的直方图(例如,使用1024, 文件尺寸为0到1023,将一个垃圾箱,1024至2047进入下一个垃圾箱等)。
。
它以参数为参数,并通过目录将文件添加到存储为双重链接列表的bin中。
例如,如果binWidth or (argv[2])
是10个,则在bin 0中存储字节尺寸0-9的文件,如果您找到了大小10或更高的文件,则会使一个新的节点具有10-18的新节点,并将其存储在此处并将其存储在此处并标记它的bin 1.
如果我有一个嵌套在另一个目录内的目录,我需要将其递归遍历文件。我有一个函数traverseNewDirectory
,旨在递归并递归地找到它们。
我相信该错误位于我的复制构造函数中。
我的代码如下:
// Directory crawler
// Written by Kaz
#include<iostream>
#include <dirent.h>
#include<string.h>
#include <errno.h>
#include <stdio.h>
#include<string>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<stdlib.h>
using namespace std;
int binCount = 0; // count of total bins which are nodes in the linked-list
struct node{
int count, name, min, max;
node* next, *prev;
node(){
name = binCount;
count = 0;
min = 0;
max = 0;
prev = NULL;
next = NULL;
}
node(node *other){
if(other == NULL){
}
else{
node* objCopy = other;
node* temp = this;
while(objCopy != NULL){
temp->next = new node;
temp->next->name = objCopy->name;
temp->next->count = objCopy->count;
temp->next->min = objCopy->min;
temp->next->max = objCopy->max;
temp->next->prev = objCopy->prev;
temp = temp->next;
objCopy = objCopy->next;
}
}
}
};
/*
void nextNode(node* previousNode, int binWidth){
node *nextLink = new node;
nextLink->count = 1;
nextLink->min = previousNode->max + 1;
nextLink->max = previousNode->max + binWidth;
nextLink->prev = previousNode;
previousNode ->next = nextLink;
}
*/
node* traverseNewDirectory(node *here, const char *dirName, int binWidth){
DIR * nwd;
struct dirent *dip;
node * current = new node(here);
// Deep copy?
//current = here;
bool isadirectory,isHidden;
if((nwd = opendir(dirName))== NULL){
perror("Can't open derived directory");
return NULL;
}
while ((dip = readdir(nwd)) != NULL){
isadirectory = false;
isHidden = false;
if((dip -> d_type) == DT_UNKNOWN ){
struct stat stbuf;
stat(dip->d_name, &stbuf);
isadirectory = S_ISDIR(stbuf.st_mode);
}
else if((dip -> d_type) == DT_DIR ){
if((strcmp(dip->d_name, ".") == 0) || (strcmp(dip->d_name, "..")) == 0){
isHidden = true;
isadirectory = true;
}
else{
isadirectory = true;
}
}
else{
if((dip-> d_reclen <= current->max)&&(dip->d_reclen >=current->min)){
current->count = current->count+1;
}
else if(dip->d_reclen < current->min){
node*temp = current->prev;
while(temp != NULL){
if((dip-> d_reclen <= temp->max)&&(dip->d_reclen >=temp->min)){
temp->count = temp->count+1;
break;
}
else if(dip->d_reclen < temp->min){
temp = temp->prev;
}
}
}
else{
current->next = new node;
current->next->count = 1;
current->next->min = current->max + 1;
current->next->max = current->max + binWidth;
current->next->prev = current;
current = current->next;
binCount++;
}
}
if(isadirectory){
string path = string(dirName) + "/"+dip->d_name;
/*
strcpy(path,dirName);
strcat(path, "/");
strcat(path,dip->d_name);
strcat(path, " ");
*/
if(isHidden == true){}
else{
current->next = new node(traverseNewDirectory(current, path.c_str(), binWidth));
if(current->next != NULL){
current = current->next;
binCount++;
}
}
}
}
while ( ( closedir (nwd) == -1) && ( errno == EINTR) );
if(current == here){
return NULL;
}
else{
return current;
}
}
void printHistogram(node *head){
node*temp;
temp = head;
while(temp!=NULL){
cout << "[B " << temp->name << "] from " << temp->min << " to " << temp->max << " : ";
for(int i = 0; i < temp->count; i++){
cout << "x";
}
cout << endl;
temp = temp->next;
}
}
int main(int argc,char *argv[]){
// Ensures that a valid directory is provided by the cmd line argument
if (argc != 3){
if(argc == 1){
fprintf (stderr, " argc = %d no directory given n", argc);
return 1;
}
else if(argc == 2){
fprintf (stderr, " argc = %d no size given n", argc);
return 2;
}
else{
fprintf(stderr, "argc = %d invalid parameters n", argc);
return 3;
}
}
DIR * cwd; // current working directory pointer
struct dirent *cwdP; // pointer to dirent struct
int binWidth; // variable for the width of the grouping in the histogram
binWidth = atoi(argv[2]);
binWidth = binWidth - 1;
node *first = new node;
first->max = binWidth;
binCount++;
node * current;
current = first;
bool isadirectory,isHidden;
if((cwd = opendir(argv[1]))== NULL){
perror("Can't open main directory");
return 2;
}
while ((cwdP = readdir(cwd)) != NULL){
isadirectory = false;
isHidden = false;
if((cwdP -> d_type) == DT_UNKNOWN ){
struct stat stbuf;
stat(cwdP->d_name, &stbuf);
isadirectory = S_ISDIR(stbuf.st_mode);
}
else if((cwdP -> d_type) == DT_DIR ){
if((strcmp(cwdP->d_name, ".") == 0) || (strcmp(cwdP->d_name, "..")) == 0){
isHidden = true;
isadirectory = true;
}
else{
isadirectory = true;
}
}
else{
if((cwdP-> d_reclen <= current->max)&&(cwdP->d_reclen >=current->min)){
current->count = current->count+1;
}
else if(cwdP->d_reclen < current->min){
node*temp = current->prev;
while(temp != NULL){
if((cwdP-> d_reclen <= temp->max)&&(cwdP->d_reclen >=temp->min)){
temp->count = temp->count+1;
break;
}
else if(cwdP->d_reclen < temp->min){
temp = temp->prev;
}
}
}
else{
/*
nextNode(current,binWidth);
current = current ->next;
//binCount++;
*/
current->next = new node;
current->next->count = 1;
current->next->min = current->max + 1;
current->next->max = current->max + binWidth;
current->next->prev = current;
current = current->next;
binCount++;
}
}
if(isadirectory){
string fullPath = string(argv[1]) + "/" + cwdP ->d_name;
/*
strcpy(path,dirName);
strcat(path, "/");
strcat(path,dip->d_name);
strcat(path, " ");
*/
if(isHidden == true){}
else{
current->next = new node(traverseNewDirectory(current, fullPath.c_str(), binWidth));
if(current->next != NULL){
current = current->next;
binCount++;
}
}
}
}
while ( ( closedir (cwd) == -1) && ( errno == EINTR) );
printHistogram(first);
return 0;
}
上次编辑
我要感谢Igor,J.H,Toby和其他所有评论的人都为我提供有关如何处理链接列表的建议。我的代码现在完全解决了问题。我能够通过将我的方法从双重链接的结构列表简化为只有几个指针而没有复制构造函数的单一链接结构列表来实现它。即使所有答案,建议和技巧都没有给我一个直接的答案,它以毅力和研究能够解决它的方式激发了我的创造力。为此,我要感谢所有花时间查看我的帖子的人。
对于复制构造函数,您可能想要这样的东西:
node(const node& other) {
node* prev = nullptr;
node* cur = this;
const node* old_cur = &other;
for (;;) {
cur->count = old_cur->count;
cur->min = old_cur->min;
cur->max = old_cur->max;
cur->prev = prev;
if (old_cur->next) {
old_cur = old_cur->next;
cur->next = new node();
prev = cur;
cur = cur->next;
} else {
cur->next = nullptr;
break;
}
}
}
尽管不清楚您甚至想要任何形式的副本或伪拷贝构造函数。traverseNewDirectory
调用可能看起来像这样:
current->next = traverseNewDirectory(...);
(丢弃new node
零件)。
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 尽管遵循了规则,内存泄漏在哪里
- 为什么调用堆栈数组会导致内存泄漏
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 使用模板类的自定义列表类型中的内存泄漏
- 为什么以下C++代码中存在内存泄漏?
- OpenCV 我应该使用智能指针来防止内存泄漏吗?
- 我是否生成线程并导致内存泄漏?
- 多线程程序中出现意外的内存泄漏
- 为什么此函数会导致内存泄漏?
- 在 C++ 库中使用cythonized python时内存泄漏
- 需要帮助查找内存泄漏
- 瓦尔格林德的内存泄漏使用新的
- 无法找出我的代码中的内存泄漏
- C++ 结构内部的unordered_map会导致内存泄漏问题吗?
- 可视化 使用 VS Code 查找C++应用程序中的内存泄漏
- Shared_ptr双链接列表内存泄漏
- C++ 在类中使用常量引用文本时 O2 内存泄漏