繁体   English   中英

无法弄清楚我在哪里有 memory 泄漏

[英]Can't figure out where I have memory leak

我是 C 的新手,仍然不知道如何使用 valgrind。 我正在做一个项目,我需要创建一个 function 每次调用时只使用一个 static 变量从文件描述符返回一行文本。

重复调用(例如,使用循环)您的 get_next_line() function 应该让您读取文件描述符指向的文本文件,一次一行。

我想出了这个,但我找不到 memory 泄漏在哪里:

char    *output(char **backup, char *rbackup, int ret, int fd)
{
    int     value;
    char    *temp;

    if (ret < 0)
        return (NULL);
    else if (ret == 0 && backup[fd] == NULL)
        return (NULL);
    value = (int)(ft_strchr(backup[fd], '\n') - backup[fd] + 1);
    rbackup = ft_substr(backup[fd], 0, value);
    temp = ft_substr(backup[fd], value, BUFFER_SIZE * BUFFER_SIZE);
    free(backup[fd]);
    if (temp[0] == '\0')
    {
        free(temp);
        temp = NULL;
    }
    backup[fd] = temp;
    return (rbackup);
}

char    *get_next_line(int fd)
{
    int         ret;
    char        buf[BUFFER_SIZE + 1];
    static char *backup[NUM_OF_FD];
    char        *rbackup;

    if (fd < 0 || fd > NUM_OF_FD)
        return (NULL);
    while (ft_strchr(backup[fd], '\n') == NULL)
    {
        ret = read(fd, buf, BUFFER_SIZE);
        buf[ret] = '\0';
        if (ret <= 0)
            break ;
        if (backup[fd] == NULL)
            backup[fd] = ft_strdup(buf);
        else
        {
            rbackup = ft_strjoin(backup[fd], buf);
            free(backup[fd]);
            backup[fd] = rbackup;
        }
    }
    return (output(backup, rbackup, ret, fd));
}

ft_函数等同于 LibC 对应函数,但如果出现错误,我将在此处发布它们:

void    *ft_memcpy(void *dst, const void *src, size_t n)
{
    size_t  i;

    i = -1;
    if ((dst != src) && n)
        while (++i < n)
            ((unsigned char *)dst)[i] = ((unsigned char *)src)[i];
    return (dst);
}

size_t  ft_strlen(const char *s)
{
    size_t  i;

    i = 0;
    while (s[i])
    {
        i++;
    }
    return (i);
}

char    *ft_strchr(const char *s, int c)
{
    char    chr;

    chr = (char)c;
    if (s == NULL)
        return (NULL);
    while (*s && *s != chr)
        s++;
    if (*s == chr)
        return ((char *)s);
    else
        return (NULL);
}

char    *ft_substr(char const *s, unsigned int start, size_t len)
{
    char    *str;

    if (!s)
        return (NULL);
    if (len > ft_strlen(s))
        len = ft_strlen(s);
    if (start > ft_strlen(s))
        len = 0;
    str = malloc(sizeof(char) * (len + 1));
    if (!str)
        return (NULL);
    str = ft_memcpy(str, &s[start], len);
    str[len] = '\0';
    return (str);
}

char    *ft_strdup(const char *s1)
{
    size_t  len;
    void    *new;

    len = ft_strlen(s1) + 1;
    new = malloc(len);
    if (new == NULL)
        return (NULL);
    return ((char *) ft_memcpy(new, s1, len));
}

char    *ft_strjoin(char const *s1, char const *s2)
{
    int     i;
    char    *str;
    size_t  size;

    if (!s1 || !s2)
        return (NULL);
    i = 0;
    size = (ft_strlen(s1) + ft_strlen(s2) + 1);
    str = malloc(sizeof(char) * size);
    if (!str)
        return (NULL);
    while (*s1)
        str[i++] = *s1++;
    while (*s2)
        str[i++] = *s2++;
    str[i] = '\0';
    return (str);
}

void    *ft_memset(void *b, int c, size_t len)
{
    size_t  i;

    i = -1;
    while (++i < len)
        ((unsigned char *)b)[i] = (unsigned char)c;
    return (b);
}

我的代码中有什么菜鸟错误吗?

好吧,我像这样运行你的代码

int main(int a, char**b)
{
   int f = open("poop.c", O_RDONLY);
   for(int i = 0; i < 10; i++)
   {
    char *x = get_next_line(f);
    printf("x");
    free(x);
   }
}

阅读前 10 行。 valgrind 没有检测到泄漏(一旦我在循环中添加了自由)

虽然它确实抱怨其他事情

==3695== Invalid read of size 1
==3695==    at 0x109270: ft_memcpy (poop.c:26)
==3695==    by 0x1093BB: ft_substr (poop.c:70)
==3695==    by 0x109619: output (poop.c:120)
==3695==    by 0x109802: get_next_line (poop.c:155)
==3695==    by 0x109857: main (poop.c:162)
==3695==  Address 0x4a4a0a5 is 0 bytes after a block of size 101 alloc'd
==3695==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==3695==    by 0x109408: ft_strdup (poop.c:81)
==3695==    by 0x109724: get_next_line (poop.c:147)
==3695==    by 0x109857: main (poop.c:162)
==3695==
==3695== Conditional jump or move depends on uninitialised value(s)
==3695==    at 0x109546: output (poop.c:114)
==3695==    by 0x109802: get_next_line (poop.c:155)
==3695==    by 0x109857: main (poop.c:162)
==3695==
==3695== Conditional jump or move depends on uninitialised value(s)
==3695==    at 0x109556: output (poop.c:116)
==3695==    by 0x109802: get_next_line (poop.c:155)
==3695==    by 0x109857: main (poop.c:162)
==3695==

似乎未初始化的读取是由读取空行引起的。

无效读取在这里

((unsigned char*)dst)[i] = ((unsigned char*)src)[i];

If you have Makefile for the C file, then you can add -g after flags in your Makefile. If you use compile the C file by clang or gcc directly, you can put -g after clang or gcc . 然后您可以获得有关您的问题的更多信息。 -g用于调试。 如果您不添加它,Valgrind 只会告诉您需要调试的部分(如特定功能)。 但是如果你添加-g ,你将能够知道你需要调试哪一行。

你肯定有以下问题:

static char *backup[NUM_OF_FD];

您检查 fd 是否大于 NUM_OF_FD,但 NUM_OF_FD 仍会尝试在备份数组之外进行索引。

if (fd < 0 || fd > NUM_OF_FD)
        return (NULL);

应该

if (fd < 0 || fd >= NUM_OF_FD)
        return (NULL);

还要注意 read() 可以返回 -1,因此这段代码可能有问题:

ret = read(fd, buf, BUFFER_SIZE);
        buf[ret] = '\0';
        if (ret <= 0)
            break ;

使用前检查返回值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM