IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    valgrind

    Yukang (moorekang@gmail.com)发表于 2011-05-06 00:00:00
    love 0

    纪念一下跑测试跑了几天才找出的一个内存泄漏,这个函数源于UNP,还以为UNP有bug呢,找到原书当getaddreinfo失败或者res==NULL的时候直接退出了。但是写这个代码的同学当然不想连接不上直接退出,于是忘记了freeaddrinfo调用直接返回,那个struct addrinfo就没释放。很多错误都是这种,涉及到库函数的时候更加难查。

    int tcp_connect(const char *host, const char *serv)
    {
            int    sockfd, n;
            struct addrinfo hints, *res, *ressave;
    
            bzero(&hints;, sizeof(struct addrinfo));
            hints.ai_family = AF_UNSPEC;
            hints.ai_socktype = SOCK_STREAM;
    
            if ( (n = getaddrinfo(host, serv, &hints;, &res;)) != 0)
            {
                    log_sprintf("tcp_connect error for %s, %s: %s", host, serv, gai_strerror(n));
                    freeaddrinfo(res); //oops: memory leak
    
                    return -1;
            }
            ressave = res;
    
            do {
                    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                    if (sockfd < 0)
                            continue;       /* ignore this one */
                    if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
                            break;          /* success */
                    close(sockfd);  /* ignore this one */
    
            } while ( (res = res->ai_next) != NULL);
    
            if (res == NULL)        /* errno set from final connect() */
            {
                    log_sprintf("tcp_connect error for %s, %s", host, serv);
                    freeaddrinfo(ressave); //oops: memory leak
                    return -1;
            }
            freeaddrinfo(ressave);
            return(sockfd);
    }

    上一篇博文中说到自己包装的内存检测方法,这还有个问题当时没发现,就是那个包装malloc之类的方法对于库函数中的内存申请调用没法记录,所以是不会发现上面这个bug的。这个Memwatch倒是把原生的malloc都重定义了,但是最好的Linux下检测内存泄漏的工具还是valgrind,这真是个神器,在代码上不用做一点修改,这东西甚至能测试程序的cache命中率。看了一下valgrind的相关论文,对于检测方法都是一种称之为shadow value的方法,也就是用信息来记录每一个byte内存的使用情况。这种方式的一个缺点都是会拖慢速度,前面提到的那种稍微包装了一下的方式可能还好(因为使用的是静态数组), Memwatch里面使用了不少链表也会拖慢速度。再看看valgrind的实现,以后工作可能会碰上类似的。

    更多valgrind 更多Memwatch


沪ICP备19023445号-2号
友情链接