使用 strlen() 时内存泄漏
memory leaks when use strlen()
我是 C 和内存管理的新手,并尝试使用 valgrind 查找内存泄漏,我在 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:
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;
};
和词法分析器结构类型:
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);
失败,因为 src
不一定指向 字符串 .
IO_ReadFile()
不会 return 指向 字符串的指针 因为该函数无法分配或附加 空字符 .
尝试
//buffer = malloc(length);
buffer = malloc(length + 1);
if (buffer)
{
fread(buffer, 1, length, f);
buffer[length] = 0; // add
}
可能存在其他问题。
I do not know why memory leaks when I use strlen()
Valgrind 未报告内存泄漏。正在报道
==49058== Invalid read of size 1
请求读取的位置是
==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)
这是已分配 space 的超过 运行,这是由于您尝试计算其长度的数据没有以空值终止。如果您希望 IO_ReadFile
提供的数据适合与字符串函数一起使用,那么它必须分配足够的 space 以在文件内容后包含一个终止符。
在 Valgrind 下不 运行 时,程序的行为可能与您预期的一样,因为在这种 over运行 上的行为是未定义的。它可能在实践中起作用,因为下一个位置恰好在程序的可访问内存 space 内(可能)并且它恰好包含一个零字节(并非难以置信,尤其是在程序的 运行 早期) .这仍然是一个严重的错误。
我是 C 和内存管理的新手,并尝试使用 valgrind 查找内存泄漏,我在 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:
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;
};
和词法分析器结构类型:
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);
失败,因为 src
不一定指向 字符串 .
IO_ReadFile()
不会 return 指向 字符串的指针 因为该函数无法分配或附加 空字符 .
尝试
//buffer = malloc(length);
buffer = malloc(length + 1);
if (buffer)
{
fread(buffer, 1, length, f);
buffer[length] = 0; // add
}
可能存在其他问题。
I do not know why memory leaks when I use
strlen()
Valgrind 未报告内存泄漏。正在报道
==49058== Invalid read of size 1
请求读取的位置是
==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)
这是已分配 space 的超过 运行,这是由于您尝试计算其长度的数据没有以空值终止。如果您希望 IO_ReadFile
提供的数据适合与字符串函数一起使用,那么它必须分配足够的 space 以在文件内容后包含一个终止符。
在 Valgrind 下不 运行 时,程序的行为可能与您预期的一样,因为在这种 over运行 上的行为是未定义的。它可能在实践中起作用,因为下一个位置恰好在程序的可访问内存 space 内(可能)并且它恰好包含一个零字节(并非难以置信,尤其是在程序的 运行 早期) .这仍然是一个严重的错误。