简体   繁体   English

使用 strlen() 时 memory 泄漏

[英]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()我是 C 和内存管理的新手,并试图用 valgrind 查找 memory 泄漏,我在lexer->src_size 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: 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循环.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词法分析器.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 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 .失败,因为src不一定指向string

IO_ReadFile() does not return a pointer to a string as the function fails to allocate for nor append a null character . IO_ReadFile()不会返回指向字符串的指针,因为 function 无法为 append 分配null 字符

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()我不知道为什么使用strlen()时 memory 会泄漏

Valgrind is not reporting a memory leak. Valgrind 没有报告 memory 泄漏。 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.这是分配空间的溢出,由您尝试计算其长度的数据未终止 null 引起。 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.如果您希望IO_ReadFile提供的数据适合与字符串函数一起使用,那么它必须分配足够的空间以在文件内容之后包含一个终止符。

It is plausible that the program behaved as you expected when not run under Valgrind because the behavior upon such an overrun is undefined.当程序不在 Valgrind 下运行时,它的行为与您预期的一样是合理的,因为这种溢出时的行为是未定义的。 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).它可能在实践中起作用,因为下一个位置恰好位于程序可访问的 memory 空间内(很可能)并且它恰好包含一个零字节(并非不可信,尤其是在程序运行的早期)。 This is nevertheless a serious error.然而,这是一个严重的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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