简体   繁体   中英

Memory leak / not properly freeing. How to fix?

I am partially reading input into a buffer in a function and then freeing it in main() but it doesn't seem to be working. My code:

char *save_to_buff()
{
    int fd = 0; // set read() to read from STDIN_FILENO, because it's number is 0
    const size_t read_size = 100; // set chunk size
    size_t size = read_size;
    char *buff = malloc(size+1);
    size_t offset = 0;
    size_t res = 0;
    while((res = read(fd, buff + offset, read_size)) > 0) // partial read from stdin and save to buff
    {
        if(res == -1) // check for read errors
        {
            read_error();
            free(buff);
            return NULL;
        }
        
        offset += res;
        if (offset + read_size > size)
        {
            size *= 2;
            buff = realloc(buff, size+1);
        }
        buff[offset] = '\0';
    }
    return buff;
}

main:

char *buff = save_to_buff();
// do sth
free(buff);

Valgrind 结果

Edit: just tried it with a 1 byte read and not a partial read and there is no memory leak.

When you read the whole file once, so the read pointer is at EOF, if you read again, as in your code, the read() will return 0, according to this . This will exit your loop without freeing the memory.

Also, depending on what type of file you are reading: Files that do not support seeking - for example, terminals - always read from the current position. The value of a file offset associated with such a file is undefined

You did not post the full code for the main() function, it is possible there is something fishy we don't see.

The function save_to_buff has some issues:

  • if stdin is already at the end of file when it starts, it will return a pointer to an uninitialized block of 101 bytes. It should either return a null pointer or a pointer to an empty string.
  • you do not test for memory allocation failure

The calling sequence in the code fragment seems fine as long as you do not modify buff in the // do sth part.

Here is a modified version:

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

char *save_to_buff() {
    int fd = 0; // set read() to read from STDIN_FILENO
    const size_t read_size = 100; // set chunk size
    size_t size = read_size;
    size_t offset = 0;
    size_t res = 0;
    char *buff = malloc(size + 1);

    if (buff == NULL)
        return NULL;
   
    *buff = '\0';
    while ((res = read(fd, buff + offset, read_size)) != 0) {
        // partial read from stdin and save to buff
        if (res == (size_t)-1) { // check for read errors
            read_error();
            free(buff);
            return NULL;
        }
        
        offset += res;
        buff[offset] = '\0';

        if (offset + read_size > size) {
            char *buff0;

            size *= 2;
            buff = realloc(buff0 = buff, size + 1);
            if (buff == NULL) {
                free(buff0);
                return NULL;
            }
        }
    }
    return buff;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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