【问题标题】:Memory Leak from C Socket Read Function来自 C 套接字读取函数的内存泄漏
【发布时间】:2023-04-04 08:26:01
【问题描述】:

我正在编写一个小代码来从套接字读取 ADS-B 数据。数据格式如下

味精,6,1,1,4242D7,1,2017/12/25,12:04:05.695,2017/12/25,12:04:05.695,,,,,,,,6142,0, 0,0, 味精,4,1,1,80068D,1,2017/12/25,12:04:05.695,2017/12/25,12:04:05.695,,,183,268,,,-576,,,,,0 味精,2,1,1,800B6F,1,2017/12/25,12:04:05.695,2017/12/25,12:04:05.695,,,7,165,28.53949,77.10886,,,,,,-1 味精,5,1,1,4242D7,1,2017/12/25,12:04:05.695,2017/12/25,12:04:05.696,KAR2440 ,32025,,,,,,,0,,0

字符串由 CRLF 终止

我目前正在使用 readline 函数逐行从套接字中读取数据

int readline(int fd, char ** out)
{
    /* Keep reading till header "MSG" is received
 * store it in buffer
 * keep reading till newline is encountered
 * exit function
 */
int buf_size = 512;
int bytesloaded = 0;
int ret;
char buf;
char * buffer = malloc(buf_size * sizeof(*buffer));
if (NULL == buffer)
{
    free(buffer);
    return -1;
}
//loop till header is received
while (1)
{
    bzero(buffer,buf_size);
    ret = read(fd, &buf, 1);
    if (ret < 0)
    {
        free(buffer);
        return -1;
    }
    if (buf=='M')   //Got M; now wait for S
    {
        bytesloaded=0;
        buffer[bytesloaded] = buf;
        bytesloaded++;
        ret = read(fd, &buf, 1);
        if (ret < 1)
        {
            free(buffer);
            return -1;
        }
        if (buf=='S')   //Got S; now wait for G
        {
            buffer[bytesloaded] = buf;
            bytesloaded++;
            ret = read(fd, &buf, 1);
            if (ret < 1)
            {
                free(buffer);
                return -1;
            }
            if (buf=='G')   //Got G; now wait for CR-LF
            {
                buffer[bytesloaded] = buf;
                bytesloaded++;
                while(1)
                {
                    ret = read(fd, &buf, 1);
                    if (ret < 1)
                    {
                        free(buffer);
                        return -1;
                    }
                    if (buf=='\n')
                        break;
                    buffer[bytesloaded] = buf;
                    bytesloaded++;
                }
                buffer[bytesloaded] = '\0';
                *out = buffer; // complete line
        //free(buffer);
                return bytesloaded;
            }
        }
    }
}
}

使用以下例程从 main 调用上述函数

bytesread=readline(netfd, &netbuf);

问题是内存中的代码占用量逐渐增加,表明内存泄漏。 Valgrind 还指向 readline 函数。 如果我取消注释倒数第二行(空闲(缓冲区)),则没有内存泄漏。但是这样做在输出时没有给我任何数据。 我在这里错过了什么。

【问题讨论】:

  • What am I missing here. 也许是free(...); ?
  • 函数int readline(int fd, char ** out)的第二个参数应该是一个在调用函数的堆栈中有空间的变量,即第二个参数应该是一个512字节的数组。此外,在代码中,您只是将指针指向本地分配的缓冲区 *out = buffer; 而不是这个,您应该在释放 buffer 指针之前使用 memcpy()。
  • 当我在 C 语言中遇到此类问题时,我使用的一个非常好的工具是 Dr. Memory。它将帮助您分析和解决内存问题。
  • 我做了一个 malloc 然后 free 为 netbuf 变量。它为我创造了另一组泄漏......所以我放弃了它。不过我会尝试 memcpy()。
  • if (NULL == buffer) { free(buffer); return -1; } 这是不正确的,如果指针为空,则无法释放它- 会出现段错误。关于您的问题,释放缓冲区应该发生在您调用 bytesread=readline(netfd, &amp;netbuf); 的函数中

标签: c sockets gcc memory-leaks valgrind


【解决方案1】:

您的设计表明函数readline 分配所需的内存并返回一个指向调用函数的指针。

使用这种设计,调用函数必须调用free 以避免内存泄漏。

我应该指出,这种设计经常会出现问题,并且会增加内存泄漏的机会。

更好的设计将内存管理问题放在一起(分配函数应该释放内存。当这不可能或不切实际时,函数名称应该清楚地表明分配并应该编写析构函数(即,line_alloc 和 @987654324 @),尽量减少混淆。

【讨论】:

    猜你喜欢
    • 2015-05-30
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2012-08-21
    相关资源
    最近更新 更多