C语言 如何在我的程序中找到内存泄漏?[关闭]

wgx48brx  于 2023-05-22  发布在  其他
关注(0)|答案(1)|浏览(77)

已关闭,此问题需要更focused。目前不接受答复。
**想改善这个问题吗?**更新问题,使其仅通过editing this post关注一个问题。

2天前关闭。
Improve this question
我正在用ncurses. h和C语言构建一个基于终端的文件查看器项目。它只是一个业余爱好的附带项目,只有几行代码。我得到了一些分割错误,我甚至没有一个线索,他们在哪里,如果有人可以检查代码,我会感激很多。

#include "window.h"
#include <dirent.h>
#include <menu.h>
#include <ncurses.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static DIR *get_dir(const char *path)
{
    DIR *dir;
    if (strcmp(path, "current") == 0)
        dir = opendir(".");
    else
        dir = opendir(path);
    if (dir == NULL)
    {
        perror("Error opening dir");
        exit(-1);
    }
    return dir;
}

WINDOW *init_window(int start_y, int start_x, int y, int x)
{
    WINDOW *win;

    initscr();
    getmaxyx(stdscr, y, x);
    cbreak();
    noecho();

    if (x < WDIM_X || y < WDIM_Y)
    {
        start_x = (x - WDIM_X_MIN);
        start_y = (y - WDIM_Y_MIN);
        win = newwin(WDIM_Y_MIN, WDIM_X_MIN, 1, 2);
    }
    else {
        start_x = (x - WDIM_X) / 2;
        start_y = (y - WDIM_Y) / 2;
        win = newwin(WDIM_Y, WDIM_X, start_y, start_x);
    }

    box(win, 0, 0);
    start_color();
    curs_set(0);

    keypad(win, true);
    init_pair(1, COLOR_BLACK, COLOR_BLUE);
    wbkgd(win, COLOR_PAIR(1));
    wrefresh(win);
    return win;
}

void delete_window(WINDOW *win)
{
    delwin(win);
    endwin();
}

char *get_current_dir()
{
    /*
    char *dirs = malloc(MAX_LENGTH * sizeof(char));
    if (getcwd(dirs, sizeof(char) * MAX_LENGTH) != NULL)
        return dirs;
    return "Error";
    */
    char *cwd = getcwd(NULL, 0);
    return cwd;
}

char **dir_items(DIR *dir)
{

    char **current_dirs = (char **)malloc(MAX_LENGTH * sizeof(char *));
    struct dirent *entry;
    int i = 0;
    while ((entry = readdir(dir)) != NULL)
    {
        char *name = entry->d_name;
        int j=i;
        while (j > 0 && strcmp(name, current_dirs[j-1]) < 0)
        {
            current_dirs[j] = current_dirs[j-1];
            j--;
        }
        current_dirs[j] = name;
        i++;
    }
    return current_dirs;
}

void cd(const char *path)
{
    if (chdir(path) == -1)
    {
        perror("Error");
    }
}

void ls(const char *path)
{
    DIR *dir = get_dir(path);
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL)
        printf("%s | %s\n", path, entry->d_name);
    closedir(dir);
}

static int n_elements(char **items)
{
    int i = 0;
    while (items[i] != NULL)
    {
        i++;
    }
    return i;
}

/* static void moveMenu(MENU *menu, WINDOW *win)
{
    char c;
    WINDOW *w;
    while ((c = wgetch(win)) != '1')
    {
        switch (c)
        {
        case 'j':
            menu_driver(menu, REQ_DOWN_ITEM);
            wrefresh(win);
            break;
        case 'k':
            menu_driver(menu, REQ_UP_ITEM);
            wrefresh(win);
            break;
        case 'q':
            delete_window(win);
            exit(-1);
            break;
        case '\n':
            delete_window(win);
            win = init_window(WDIM_Y, WDIM_X, 5, 5);
            cd("/");
            sleep(3);
            render_dir(win);
            break;
        }
    }
} */

void render_dir(WINDOW *win)
{
    char **items_chars, *titulo, c;
    int i=0, x, y;
    int n;
    DIR *dir;
    ITEM **items;
    MENU *menu;
    char *path = get_current_dir();
    path = strcat(path, "/");
    dir = get_dir(path);
    items_chars = dir_items(dir);

    wclear(win);
    titulo = malloc(MAX_LENGTH * sizeof(char));
    strcpy(titulo, get_current_dir(path));
    mvwprintw(win, 0, 1, titulo);
    wrefresh(win);
    n = n_elements(items_chars);
    items = (ITEM **)calloc(n + 1, sizeof(ITEM *));

    for (int j = 0; j < n; j++)
    {
        items[j] = new_item(items_chars[j], "");
    }
    // final have to be NULL
    items[n] = (ITEM *)NULL;

    menu = new_menu(items);
    set_menu_win(menu, win);
    set_menu_sub(menu, derwin(win, 25, 40, 2, 1));
    // set_menu_fore(menu, A_NORMAL);
    set_menu_format(menu, 25, 1);
    set_menu_back(menu, COLOR_PAIR(1));
    post_menu(menu);
    wrefresh(win);
    while ((c = wgetch(win)) != '1')
    {
        switch (c)
        {
        case 'j':
            menu_driver(menu, REQ_DOWN_ITEM);
            if (i > n)
                i = n;
            else
                i++;
            //i++;
            wrefresh(win);
            break;
        case 'k':
            menu_driver(menu, REQ_UP_ITEM);
            if (i < 0)
                i = 0;
            else
                i--;
            //i--;
            wrefresh(win);
            break;
            break;
        case 'q':
            delete_window(win);
            exit(-1);
            break;
        case '\n':
            for (int j = 0; j < n; j++)
            {
                free_item(items[j]);
            }
            free_menu(menu);
            path = strcat(path, items_chars[i]);
            free(items_chars);
            free(titulo);
            closedir(dir);
            wclear(win);
            delwin(win);
            getmaxyx(stdscr, y, x);
            if (x < WDIM_X || y < WDIM_Y)
                win = init_window(WDIM_Y_MIN, WDIM_X_MIN, 5, 5);
            else
                win = init_window(WDIM_Y, WDIM_X, 5, 5);
            cd(path);
            free(path);
            mvwprintw(win, 20, 1, "s");
            render_dir(win);
            break;
        }
    }

    wrefresh(win);
}

这里是主

#include "window.h"

int main(int argc, char **argv)
{
    WINDOW *win;
    win = init_window(WDIM_Y, WDIM_X, 5, 5);
    render_dir(win);
    delete_window(win);
    return 0;
}

我已经尝试以各种方式释放所有内存,但它仍然存在分段错误和内存泄漏。

bd1hkmkf

bd1hkmkf1#

问题(或者说是一个问题,可能还有其他问题)是你正在这样做:

char *path = get_current_dir();
path = strcat(path, "/");

get_current_dir()这样做:

char *cwd = getcwd(NULL, 0);
return cwd;

根据man pagegetcwd()可以执行此操作
作为POSIX.1-2001标准的扩展,如果buf为NULL,glibc的getcwd()使用malloc(3)动态分配缓冲区。在这种情况下,当buf被分配为所需的大小时,所分配的缓冲区具有长度大小,除非大小为零。调用者应该释放(3)返回的缓冲区。
因此返回的缓冲区正好是路径的大小。没有空间添加'/'
所以这个:

path = strcat(path, "/");

导致缓冲区溢出和未定义的行为。

相关问题