如何修复C程序中可能丢失的字节

如何修复C程序中可能丢失的字节,c,memory,valgrind,memory-leak-detector,C,Memory,Valgrind,Memory Leak Detector,我做过一个项目,目标是在每次调用函数(get_nl)时读取一行文件。一行是“\n”前面的所有字符。 我尝试使用链表,以便能够同时读取多个文件 但它似乎在泄漏内存,我真的不知道如何或从何处泄漏。我使用valgrind,您可以检查下面的输出我刚刚使用了标志--leak check=full 下面是我的代码: 我的助手功能: #包括“header.h” 字符*ft_strchr(常量字符*s,整数c) { 尺寸i; i=0; 而(s[i]!=c) { 如果(!(s[i])) 返回(空); i++; }

我做过一个项目,目标是在每次调用函数(get_nl)时读取一行文件。
一行是“\n”前面的所有字符。
我尝试使用链表,以便能够同时读取多个文件

但它似乎在泄漏内存,我真的不知道如何或从何处泄漏。我使用valgrind,您可以检查下面的输出

我刚刚使用了标志--leak check=full

下面是我的代码:

我的助手功能:
#包括“header.h”
字符*ft_strchr(常量字符*s,整数c)
{
尺寸i;
i=0;
而(s[i]!=c)
{
如果(!(s[i]))
返回(空);
i++;
}
返回((字符*)s+i);
}
尺寸英尺(常量字符*s)
{
尺寸i;
i=0;
而(s[i])
i++;
回报(i);
}
大小长度(常量字符*s,大小长度)
{
尺寸i;
i=0;
而(i
我的核心职能
#包括“header.h”
#包括
空隙*ft_memalloc(尺寸)
{
char*str;
尺寸i;
i=0;
如果(!(str=(char*)malloc(sizeof(char)*(size)))
返回(空);
而(ifd=fd;
}
温度=(*alst);
而(临时->下一步!=NULL&&temp->fd!=fd)
温度=温度->下一步;
如果(temp->next==NULL&&temp->fd!=fd)
{
如果(!(temp->next=ft_memalloc(sizeof(t_list)))
返回(空);
临时->下一步->fd=fd;
温度=温度->下一步;
temp->next=NULL;
}
返回(临时);
}
int ft_换行符(字符**str,字符**line,int r)
{
char*pos;
char*tmp;
尺寸i;
如果(*str==NULL&&r==0)
返回(0);
如果((pos=ft_strhr((*str),'\n'))==NULL&&r==0&&str)
{
如果(ft_strlen(*str)==0)
{
*直线=英尺/平方英尺(“,0);
返回(0);
}
如果(!(*line=ft_strndup((*str),ft_strlen(*str)))
返回(-1);
金融时报(str);
返回(0);
}
i=(pos-*str);
如果(!(*line=ft_strndup((*str),i))
||!(tmp=ft_strndup(&(*str)[i+1],ft_strlen(&(*str)[i+1]))
返回(-1);
游离((*str));
(*str)=tmp;
申报表(1);
}
char*ft_strjoin(char const*s1,char const*s2,int-tofree)
{
char*s;
尺寸i;
尺寸j;
大小;
i=-1;
j=-1;
如果(s1==NULL | | s2==NULL)
返回(空);
尺寸=英尺(s1)+英尺(s2);
如果(!(s=(char*)malloc(sizeof(char)*size+1)))
返回(空);
而(s1[++i])
s[i]=s1[i];
而(s2[++j])
s[i+j]=s2[j];
s[i+j]='\0';
if(tofree&1)
自由((字符*)s1);
如果(tofree&2)
自由((字符*)s2);
申报表;
}
int get_nl(int fd,字符**行)
{
INTR;
char buf[缓冲区大小+1];
静态t_列表*头;
如果(缓冲区大小<1 | | fd<0 | |读取(fd,buf,0)||
!(head=ft_已分配(&head,fd))| |!行)
返回(-1);
而((r=read(fd,&buf,BUFFER_SIZE))>0)
{
buf[r]='\0';
if(head->tmp==NULL)
head->tmp=ft_strndup(buf,ft_strlen(buf));
其他的
头部->tmp=ft_strjoin(头部->tmp,buf,1);
如果(ft_strchr(head->tmp,'\n'))
返回(ft_新行(&(head->tmp),行,r));
}
返回(ft_新行(&(head->tmp),行,r));
}
内部主(内部ac,字符**av)
{
int-fd;
字符*行;
INTR;
(无效)ac;
行=空;
r=0;
fd=开路(仅限av[1];
r=获取下一行(fd和行);
自由线;
}
我的头文件:
#ifndef头
#定义标题
#包括
#包括
#包括
类型定义结构s_列表
{
int-fd;
char*tmp;
结构s_列表*下一步;
}t_列表;
t\u列表*ft\u已分配(t\u列表**alst,const int fd);
int ft_换行符(字符**str,字符**line,int r);
int get_nl(常量int fd,字符**行);
空隙*ft_memalloc(尺寸);
字符*ft_strchr(常量字符*s,整数c);
尺寸(常量字符*s);
大小(常量字符*s,大小长度);
无效格式(字符**as);
字符*ft\u strndup(常量字符*s,大小\u t n);
char*ft_strjoin(char const*s1,char const*s2,int-tofree);
#恩迪夫
编辑:
我不知道我是怎么弄丢的,但它不再显示了,我添加了调试标志-g3

考虑:你是如何释放从
get\u nl
调用的函数分配的内存的,这些函数存储在该函数的静态
head
变量中?我不确定Mac Valgrind,但是,如果Linux Valgrind正在分析的可执行文件包含调试信息,那么它肯定会在堆栈跟踪中包含行号。这会让你很好地了解哪些内存正在(可能)泄漏,这将是找出它是如何泄漏的一个重要步骤。
get\u nl
是否与
get\u next\u line
相同?@IanAbbott是的。我没有成功地解决我的问题。我看了看我的ft_strjoin和ft_strndup,但在我的strjoin中,如果有需要,我可以在我的strndup中释放
==30653== Memcheck, a memory error detector
==30653== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==30653== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==30653== Command: ./a.out
==30653== Parent PID: 20837
==30653== 
==30653== Syscall param open(filename) points to unaddressable byte(s)
==30653==    at 0x10062D862: open (in /usr/lib/system/libsystem_kernel.dylib)
==30653==    by 0x100000D11: main (get_next_line.c:145)
==30653==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==30653== 
==30653== 
==30653== HEAP SUMMARY:
==30653==     in use at exit: 22,577 bytes in 167 blocks
==30653==   total heap usage: 188 allocs, 21 frees, 31,025 bytes allocated
==30653== 
==30653== 72 bytes in 3 blocks are possibly lost in loss record 26 of 43
==30653==    at 0x1000AC6EA: calloc (in /usr/local/Cellar/valgrind/3.15.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==30653==    by 0x1007567E2: map_images_nolock (in /usr/lib/libobjc.A.dylib)
==30653==    by 0x1007697DA: objc_object::sidetable_retainCount() (in /usr/lib/libobjc.A.dylib)
==30653==    by 0x100007C64: dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) (in /usr/lib/dyld)
==30653==    by 0x100007E39: dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) (in /usr/lib/dyld)
==30653==    by 0x10022171D: _dyld_objc_notify_register (in /usr/lib/system/libdyld.dylib)
==30653==    by 0x100756075: _objc_init (in /usr/lib/libobjc.A.dylib)
==30653==    by 0x1001ABB34: _os_object_init (in /usr/lib/system/libdispatch.dylib)
==30653==    by 0x1001ABB1B: libdispatch_init (in /usr/lib/system/libdispatch.dylib)
==30653==    by 0x1000BA9C2: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==30653==    by 0x100019AC5: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==30653==    by 0x100019CF5: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==30653== 
==30653== LEAK SUMMARY:
==30653==    definitely lost: 0 bytes in 0 blocks
==30653==    indirectly lost: 0 bytes in 0 blocks
==30653==      possibly lost: 72 bytes in 3 blocks
==30653==    still reachable: 200 bytes in 6 blocks
==30653==         suppressed: 22,305 bytes in 158 blocks
==30653== Reachable blocks (those to which a pointer was found) are not shown.
==30653== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==30653== 
==30653== For lists of detected and suppressed errors, rerun with: -s
==30653== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 12)

#include "header.h"

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

    i = 0;
    while (s[i] != c)
    {
        if (!(s[i]))
            return (NULL);
        i++;
    }
    return ((char *)s + i);
}

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

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

size_t  ft_strnlen(const char *s, size_t len)
{
    size_t  i;

    i = 0;
    while (i < len && *s)
        i++;
    return (i);
}

void    ft_strdel(char **alst)
{
    free(*alst);
    *alst = NULL;
}

char    *ft_strndup(const char *s, size_t n)
{
    char    *str;
    size_t  i;

    i = -1;
    if (!(str = (char *)malloc(sizeof(char) * ft_strnlen(s, n) + 1)))
        return (NULL);
    while (++i < n)
        str[i] = s[i];
    str[i] = '\0';
    return (str);
}
#include "header.h"
#include <fcntl.h>

void    *ft_memalloc(size_t size)
{
    char    *str;
    size_t  i;

    i = 0;
    if (!(str = (char *)malloc(sizeof(char) * (size))))
        return (NULL);
    while (i < size)
    {
        str[i] = 0;
        i++;
    }
    return (str);
}

t_list  *ft_is_allocated(t_list **alst, const int fd)
{
    t_list  *temp;

    if (!(*alst))
    {
        if (!((*alst) = ft_memalloc(sizeof(t_list))))
            return (NULL);
        (*alst)->fd = fd;
    }
    temp = (*alst);
    while (temp->next != NULL && temp->fd != fd)
        temp = temp->next;
    if (temp->next == NULL && temp->fd != fd)
    {
        if (!(temp->next = ft_memalloc(sizeof(t_list))))
            return (NULL);
        temp->next->fd = fd;
        temp = temp->next;
        temp->next = NULL;
    }
    return (temp);
}

int     ft_newline(char **str, char **line, int r)
{
    char            *pos;
    char            *tmp;
    size_t          i;

    if (*str == NULL && r == 0)
        return (0);
    if ((pos = ft_strchr((*str), '\n')) == NULL && r == 0 && *str)
    {
        if (ft_strlen(*str) == 0)
        {
            *line = ft_strndup("", 0);
            return (0);
        }
        if (!(*line = ft_strndup((*str), ft_strlen(*str))))
            return (-1);
        ft_strdel(str);
        return (0);
    }
    i = (pos - *str);
    if (!(*line = ft_strndup((*str), i))
        || !(tmp = ft_strndup(&(*str)[i + 1], ft_strlen(&(*str)[i + 1]))))
        return (-1);
    free((*str));
    (*str) = tmp;
    return (1);
}

char    *ft_strjoin(char const *s1, char const *s2, int tofree)
{
    char    *s;
    size_t  i;
    size_t  j;
    size_t  size;

    i = -1;
    j = -1;
    if (s1 == NULL || s2 == NULL)
        return (NULL);
    size = ft_strlen(s1) + ft_strlen(s2);
    if (!(s = (char *)malloc(sizeof(char) * size + 1)))
        return (NULL);
    while (s1[++i])
        s[i] = s1[i];
    while (s2[++j])
        s[i + j] = s2[j];
    s[i + j] = '\0';
    if (tofree & 1)
        free((char *)s1);
    if (tofree & 2)
        free((char *)s2);
    return (s);
}

int     get_nl(int fd, char **line)
{
    int             r;
    char            buf[BUFFER_SIZE + 1];
    static t_list   *head;

    if (BUFFER_SIZE < 1 || fd < 0 || read(fd, buf, 0) ||
        !(head = ft_is_allocated(&head, fd)) || !line)
        return (-1);
    while ((r = read(fd, &buf, BUFFER_SIZE)) > 0)
    {
        buf[r] = '\0';
        if (head->tmp == NULL)
            head->tmp = ft_strndup(buf, ft_strlen(buf));
        else
            head->tmp = ft_strjoin(head->tmp, buf, 1);
        if (ft_strchr(head->tmp, '\n'))
            return (ft_newline(&(head->tmp), line, r));
    }
    return (ft_newline(&(head->tmp), line, r));
}

int     main(int ac, char **av)
{
    int     fd;
    char    *line;
    int     r;
    (void)  ac;


    line = NULL;
    r = 0;
    fd = open(av[1], O_RDONLY);
    r = get_next_line(fd, &line);
    free(line);
}
#ifndef HEADER_H
# define HEADER_H

# include <stdlib.h>
# include <unistd.h>
# include <stdio.h>

typedef struct      s_list
{
    int             fd;
    char            *tmp;
    struct s_list   *next;
}                   t_list;

t_list              *ft_is_allocated(t_list **alst, const int fd);
int                 ft_newline(char **str, char **line, int r);
int                 get_nl(const int fd, char **line);

void                *ft_memalloc(size_t size);
char                *ft_strchr(const char *s, int c);
size_t              ft_strlen(const char *s);
size_t              ft_strnlen(const char *s, size_t len);
void                ft_strdel(char **as);
char                *ft_strndup(const char *s, size_t n);
char                *ft_strjoin(char const *s1, char const *s2, int tofree);

#endif