简体   繁体   中英

memory leaks when use strlen()

im new to C and memory-management and tried to find memory leaks with valgrind, and i found all problems in lexer->src_size I do not know why memory leaks when I use strlen()

valgrind:

==49058== Memcheck, a memory error detector
==49058== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==49058== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==49058== Command: ./loop -s
==49058== 
==49058== Invalid read of size 1
==49058==    at 0x483FF54: strlen (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x1093D1: Lexer_Init (lexer.c:11)
==49058==    by 0x109A44: Loop_Compile (loop.c:6)
==49058==    by 0x109AD4: main (in /home/ali/Desktop/loop/loop)
==49058==  Address 0x4a502be is 0 bytes after a block of size 30 alloc'd
==49058==    at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x109366: IO_ReadFile (io.c:17)
==49058==    by 0x109ACC: main (in /home/ali/Desktop/loop/loop)
==49058== 
==49058== Conditional jump or move depends on uninitialised value(s)
==49058==    at 0x483FC57: strcat (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x10955A: Lexer_LexID (lexer.c:54)
==49058==    by 0x109691: Lexer_NextToken (lexer.c:82)
==49058==    by 0x109A80: Loop_Compile (loop.c:8)
==49058==    by 0x109AD4: main (in /home/ali/Desktop/loop/loop)
==49058==  Uninitialised value was created by a heap allocation
==49058==    at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x1093B6: Lexer_Init (lexer.c:9)
==49058==    by 0x109A44: Loop_Compile (loop.c:6)
==49058==    by 0x109AD4: main (in /home/ali/Desktop/loop/loop)
==49058== 
void: 0
main: 0
): 8
{: 9
==49058== Conditional jump or move depends on uninitialised value(s)
==49058==    at 0x483FC57: strcat (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x1095F3: Lexer_LexNumber (lexer.c:69)
==49058==    by 0x1096DD: Lexer_NextToken (lexer.c:86)
==49058==    by 0x109A80: Loop_Compile (loop.c:8)
==49058==    by 0x109AD4: main (in /home/ali/Desktop/loop/loop)
==49058==  Uninitialised value was created by a heap allocation
==49058==    at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x1093B6: Lexer_Init (lexer.c:9)
==49058==    by 0x109A44: Loop_Compile (loop.c:6)
==49058==    by 0x109AD4: main (in /home/ali/Desktop/loop/loop)
==49058== 
1: 2
+: 4
2: 2
==49058== Invalid read of size 1
==49058==    at 0x109454: Lexer_Advance (lexer.c:22)
==49058==    by 0x109480: Lexer_AdvanceWithToken (lexer.c:28)
==49058==    by 0x10991A: Lexer_NextToken (lexer.c:115)
==49058==    by 0x109A80: Loop_Compile (loop.c:8)
==49058==    by 0x109AD4: main (in /home/ali/Desktop/loop/loop)
==49058==  Address 0x4a502be is 0 bytes after a block of size 30 alloc'd
==49058==    at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==49058==    by 0x109366: IO_ReadFile (io.c:17)
==49058==    by 0x109ACC: main (in /home/ali/Desktop/loop/loop)
==49058== 
}: 10
==49058== 
==49058== HEAP SUMMARY:
==49058==     in use at exit: 234 bytes in 15 blocks
==49058==   total heap usage: 28 allocs, 13 frees, 5,884 bytes allocated
==49058== 
==49058== LEAK SUMMARY:
==49058==    definitely lost: 168 bytes in 10 blocks
==49058==    indirectly lost: 66 bytes in 5 blocks
==49058==      possibly lost: 0 bytes in 0 blocks
==49058==    still reachable: 0 bytes in 0 blocks
==49058==         suppressed: 0 bytes in 0 blocks
==49058== Rerun with --leak-check=full to see details of leaked memory
==49058== 
==49058== For lists of detected and suppressed errors, rerun with: -s
==49058== ERROR SUMMARY: 12 errors from 4 contexts (suppressed: 0 from 0)

io.c:


char *IO_ReadFile(const char *filename)
{
    char *buffer = 0;
    long length;
    FILE *f = fopen(filename, "rb");

    if (f)
    {
        fseek(f, 0, SEEK_END);
        length = ftell(f);
        fseek(f, 0, SEEK_SET);
        buffer = malloc(length);
        if (buffer)
        {
            fread(buffer, 1, length, f);
        }
        fclose(f);
    }

    return buffer;
}

loop.c

void Loop_Compile(char *src)
{
    lexer_t *lexer = Lexer_Init(src);
    token_t *token = 0;
    while ((token = Lexer_NextToken(lexer))->kind != TOKEN_EOF)
    {
        printf("%s: %d\n", token->value, token->kind);
    }
}

lexer.c

lexer_t *Lexer_Init(char *src)
{
    lexer_t *lexer = malloc(sizeof(lexer_t));
    lexer->src = src;
    lexer->src_size = strlen(src); // <----- Here
    lexer->index = 0;
    lexer->cc = src[lexer->index];
    return lexer;
};

and lexer struct type:

typedef struct LEXER_STRUCT
{
    char *src;
    size_t src_size;
    char cc; // cc: current char
    unsigned int index;
} lexer_t;

main.c

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Please Add A File\n");
        return 1;
    }
    Loop_Compile(IO_ReadFile("./examples/main.loop"));
    return 0;
}

strlen(src); fails as src does not certainly point to a string .

IO_ReadFile() does not return a pointer to a string as the function fails to allocate for nor append a null character .

Try

    //buffer = malloc(length);
    buffer = malloc(length + 1);
    if (buffer)
    {
        fread(buffer, 1, length, f);
        buffer[length] = 0; // add
    }

Other issue may exist.

I do not know why memory leaks when I use strlen()

Valgrind is not reporting a memory leak. It is reporting

==49058== Invalid read of size 1

and the location on which the read was requested is

==49058== Address 0x4a502be is 0 bytes after a block of size 30 alloc'd ==49058== at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==49058== by 0x109366: IO_ReadFile (io.c:17)

This is an overrun of the allocated space, arising from the data whose length you are trying to compute not being null terminated. If you want the data provided by IO_ReadFile to be suitable for use with string functions then it must allocate enough space to include a terminator after the contents of the file.

It is plausible that the program behaved as you expected when not run under Valgrind because the behavior upon such an overrun is undefined. It may work in practice because the next location happens to be within the program's accessible memory space (likely) and it happens to contain a zero byte (not implausible, especially early in the run of the program). This is nevertheless a serious error.

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