双链接结构列表的内存泄漏

Memory leak of doubly linked struct list

本文关键字:内存 泄漏 列表 链接 结构      更新时间:2023-10-16

我正在使用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零件)。