Valgrind抱怨内存泄漏

Too*_*204 3 c memory-leaks memory-management

我有一个C程序,在命令行上接收标志和文件。为了处理文件,我将它们放入动态分配的类型的char**数组中,Valgrind抱怨使用此数组时

==14389== Memcheck, a memory error detector
==14389== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14389== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14389== Command: ./main
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x4838931: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x10931B: Options_append_filename (main.c:53)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Invalid write of size 8
==14389==    at 0x10934A: Options_append_filename (main.c:54)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389==  Address 0x4a53090 is 0 bytes inside a block of size 1 alloc'd
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A9B8: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A9C7: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9D9: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9E3: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9E5: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9F4: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Invalid write of size 8
==14389==    at 0x10938D: Options_append_filename (main.c:56)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389==  Address 0x4a53098 is 7 bytes after a block of size 1 alloc'd
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x1095AE: main (main.c:113)
==14389== 
==14389== Invalid read of size 8
==14389==    at 0x1095A8: main (main.c:113)
==14389==  Address 0x4a53098 is 7 bytes after a block of size 1 alloc'd
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48C2F73: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A852: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48C431D: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A864: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48C431D: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48F1993: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1224)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x48F1995: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1226)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48F19A6: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1224)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x48F19A8: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1226)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48F19D0: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1224)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x48F19C4: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1226)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483EA3F: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483EA57: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483EA5C: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483EA70: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483EA81: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
opts.files[0] is: './main'
==14389== 
==14389== HEAP SUMMARY:
==14389==     in use at exit: 8 bytes in 2 blocks
==14389==   total heap usage: 4 allocs, 2 frees, 1,040 bytes allocated
==14389== 
==14389== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== 7 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14389==    at 0x483774F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109349: Options_append_filename (main.c:54)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== LEAK SUMMARY:
==14389==    definitely lost: 8 bytes in 2 blocks
==14389==    indirectly lost: 0 bytes in 0 blocks
==14389==      possibly lost: 0 bytes in 0 blocks
==14389==    still reachable: 0 bytes in 0 blocks
==14389==         suppressed: 0 bytes in 0 blocks
==14389== 
==14389== For counts of detected and suppressed errors, rerun with: -v
==14389== Use --track-origins=yes to see where uninitialised values come from
==14389== ERROR SUMMARY: 48 errors from 27 contexts (suppressed: 0 from 0)
Run Code Online (Sandbox Code Playgroud)

我试着用数据等初始化数组

==14389== Memcheck, a memory error detector
==14389== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14389== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14389== Command: ./main
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x4838931: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x10931B: Options_append_filename (main.c:53)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Invalid write of size 8
==14389==    at 0x10934A: Options_append_filename (main.c:54)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389==  Address 0x4a53090 is 0 bytes inside a block of size 1 alloc'd
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A9B8: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A9C7: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9D9: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9E3: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9E5: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483A9F4: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109373: Options_append_filename (main.c:55)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Invalid write of size 8
==14389==    at 0x10938D: Options_append_filename (main.c:56)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389==  Address 0x4a53098 is 7 bytes after a block of size 1 alloc'd
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x1095AE: main (main.c:113)
==14389== 
==14389== Invalid read of size 8
==14389==    at 0x1095A8: main (main.c:113)
==14389==  Address 0x4a53098 is 7 bytes after a block of size 1 alloc'd
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48C2F73: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A852: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48C431D: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483A864: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48C431D: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48F1993: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1224)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x48F1995: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1226)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48F19A6: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1224)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x48F19A8: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1226)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x48F19D0: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1224)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x48F19C4: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1226)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483EA3F: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483EA57: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Conditional jump or move depends on uninitialised value(s)
==14389==    at 0x483EA5C: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483EA70: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
==14389== Use of uninitialised value of size 8
==14389==    at 0x483EA81: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x48F1951: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1243)
==14389==    by 0x48C3018: vfprintf (vfprintf.c:1638)
==14389==    by 0x48CB995: printf (printf.c:33)
==14389==    by 0x1095E2: main (main.c:117)
==14389== 
opts.files[0] is: './main'
==14389== 
==14389== HEAP SUMMARY:
==14389==     in use at exit: 8 bytes in 2 blocks
==14389==   total heap usage: 4 allocs, 2 frees, 1,040 bytes allocated
==14389== 
==14389== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14389==    at 0x483998B: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x1092DA: Options_append_filename (main.c:44)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== 7 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14389==    at 0x483774F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14389==    by 0x109349: Options_append_filename (main.c:54)
==14389==    by 0x1094B9: parse_cmdline (main.c:85)
==14389==    by 0x109544: main (main.c:98)
==14389== 
==14389== LEAK SUMMARY:
==14389==    definitely lost: 8 bytes in 2 blocks
==14389==    indirectly lost: 0 bytes in 0 blocks
==14389==      possibly lost: 0 bytes in 0 blocks
==14389==    still reachable: 0 bytes in 0 blocks
==14389==         suppressed: 0 bytes in 0 blocks
==14389== 
==14389== For counts of detected and suppressed errors, rerun with: -v
==14389== Use --track-origins=yes to see where uninitialised values come from
==14389== ERROR SUMMARY: 48 errors from 27 contexts (suppressed: 0 from 0)
Run Code Online (Sandbox Code Playgroud)

chq*_*lie 7

这里至少有一个内存泄漏:

opts.files = malloc(sizeof(NULL));
opts.files = NULL;
Run Code Online (Sandbox Code Playgroud)

您的大小分配内存NULL,这是没有意义的NULL,可以定义为0((void*)0)可能具有不同的尺寸,而你立即覆盖这个指针用opts.files = NULL,使分配的内存块不可达。您应该为一个指针分配空间并将其初始化为NULL

还有另一个泄漏Options_cleanup_mem:您忘记释放指向的数组opts->files

传入的大小tmp = realloc(opts->files, num_files + 1);不正确,您应该根据元素大小大幅增加元素数量sizeof(opts->files[0])。此外,新的元素数为num_files + 2,包括新的文件名和空终止符。

这行free(opts->files[num_files]);是多余的,Options_append_filename因为它opts->files[num_files]是一个NULL指针。

您应在中出现所有错误情况下退出程序parse_cmdline()

main()使用with 返回之前,应该释放分配的内存,Options_cleanup_mem(&opts);以便valgrind不会诊断未释放的内存。

这是修改后的版本:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct {
    bool help_flag;
    bool version_flag;
    char **files;
} Options;

Options Options_new(void) {
    Options opts;
    opts.help_flag = false;
    opts.version_flag = false;

    opts.files = malloc(sizeof(opts.files[0]));
    opts.files[0] = NULL;
    return opts;
}

void Options_cleanup_mem(Options *opts) {
    int i = 0;
    if (opts->files) {
        while (opts->files[i] != NULL)
            free(opts->files[i++]);

        free(opts->files);
    }
}

int Options_append_filename(Options *opts, const char *filename) {
    int num_files = 0;
    char **tmp;
    while (opts->files[num_files] != NULL)
        num_files++;

    tmp = realloc(opts->files, sizeof(opts->files[0]) * (num_files + 2));

    /* Handle case where realloc can't allocate memory */
    if (tmp == NULL) {
        return -1;
    }

    opts->files = tmp;
    opts->files[num_files] = malloc(strlen(filename) + 1);
    strcpy(opts->files[num_files], filename);
    opts->files[num_files + 1] = NULL;

    return 0;
}

Options parse_cmdline(int argc, char **argv) {
    Options opts = Options_new();
    for (int a = 0; a < argc; a++) {
        if (argv[a][0] == '-') {
            char *longopt = argv[a];
            if (!strcmp(longopt, "--help")) {
                opts.help_flag = true;
            } else if (!strcmp(longopt, "--version")) {
                opts.version_flag = true;
            } else {
                fprintf(stderr, "Unkown option\n");
                Options_cleanup_mem(&opts);
                exit(1);
            }
        } else {
            if (Options_append_filename(&opts, argv[a]) != 0) {
                fprintf(stderr, "Error processing arguments\n");
                Options_cleanup_mem(&opts);
                exit(1);
            }
        }
    }

    return opts;
}

int main(int argc, char **argv) {
    Options opts = parse_cmdline(argc, argv);

    if (opts.help_flag) {
        printf("Help message\n");
        return 2;
    }

    if (opts.version_flag) {
        printf("Version message\n");
        return 2;
    }

    int i = 0;
    while (opts.files[i] != NULL)
        i++;

    for (int a = 0; a < i; a++)
        printf("opts.files[%d] is: '%s'\n", a, opts.files[a]);

    Options_cleanup_mem(&opts);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • Options按值返回结构时,很难处理内存分配失败。Options_new应该使用一个指针并返回错误状态。
  • 您测试realloc()失败,但不测试其他malloc()失败。
  • 您应该将数组大小存储在Options结构内部,以避免在各处重新计算。