【问题标题】:Memory Leak when returning char *返回 char 时内存泄漏 *
【发布时间】:2021-11-01 11:20:23
【问题描述】:

我正在尝试将 const char * 转换为 set 然后返回它,它也给了我正确的输出。但是valgrind 说它有内存泄漏。我在 Arch linux 上使用 gcc 版本 11.1.0 (GCC) x64_86。

这是我的代码

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

#define true 0
#define false 1

char *to_set(const char *a); // fix missing prototype
char *to_set(const char *a)
{
    if (a)
    {
        size_t len = strlen(a);
        size_t cnt = 0, map_append = 0, o = 0;
        int check = false;
        char *set_char = (char *)malloc((sizeof(char) * len) + 1);
        strcpy(set_char, "\0");
        for (cnt = 0; cnt < len; cnt++)
        {
            check = false;
            for (o = 0; set_char[o] != '\0'; o++)
            {
                if (set_char[o] == a[cnt])
                {
                    check = true;
                    break;
                }
            }
            if (check == false)
            {
                set_char[map_append] = a[cnt];
                map_append++;
            }
        }
        return set_char;
    }
    return (char *)NULL; // else case
}

int main(int argc, char const *argv[])
{
    if (argv[1] != NULL)
    {
        char *buff = to_set(argv[1]);
        printf("'%s'\n", buff);
    }
    else
        printf("no input\n");
    return 0;
}

Valgrind 错误消息:

==19499== Memcheck, a memory error detector
==19499== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19499== Using Valgrind-3.17.0-07f0cdcbb4-20210319X and LibVEX; rerun with -h for copyright info
==19499== Command: ./main HelloWorld
==19499== Parent PID: 16246
==19499== 
--19499-- 
--19499-- Valgrind options:
--19499--    --leak-check=full
--19499--    --show-leak-kinds=all
--19499--    --track-origins=yes
--19499--    --verbose
--19499--    --log-file=valgrind-out.txt
--19499-- Contents of /proc/version:
--19499--   Linux version 5.13.13-arch1-1 (linux@archlinux) (gcc (GCC) 11.1.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP PREEMPT Thu, 26 Aug 2021 19:14:36 +0000
--19499-- 
--19499-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand-rdseed
--19499-- Page sizes: currently 4096, max supported 4096
--19499-- Valgrind library directory: /usr/lib/valgrind
--19499-- Reading syms from /home/tushar/Desktop/main
--19499--    object doesn't have a symbol table
--19499-- Reading syms from /usr/lib/ld-2.33.so
--19499-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux
--19499--    object doesn't have a dynamic symbol table
--19499-- Scheduler: using generic scheduler lock implementation.
--19499-- Reading suppressions file: /usr/lib/valgrind/default.supp
==19499== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-19499-by-tushar-on-???
==19499== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-19499-by-tushar-on-???
==19499== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-19499-by-tushar-on-???
==19499== 
==19499== TO CONTROL THIS PROCESS USING vgdb (which you probably
==19499== don't want to do, unless you know exactly what you're doing,
==19499== or are doing some strange experiment):
==19499==   /usr/lib/valgrind/../../bin/vgdb --pid=19499 ...command...
==19499== 
==19499== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==19499==   /path/to/gdb ./main
==19499== and then give GDB the following command
==19499==   target remote | /usr/lib/valgrind/../../bin/vgdb --pid=19499
==19499== --pid is optional if only one valgrind process is running
==19499== 
--19499-- REDIR: 0x4023890 (ld-linux-x86-64.so.2:strlen) redirected to 0x580bb342 (vgPlain_amd64_linux_REDIR_FOR_strlen)
--19499-- REDIR: 0x4023660 (ld-linux-x86-64.so.2:index) redirected to 0x580bb35c (vgPlain_amd64_linux_REDIR_FOR_index)
--19499-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so
--19499-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
==19499== WARNING: new redirection conflicts with existing -- ignoring it
--19499--     old: 0x04023890 (strlen              ) R-> (0000.0) 0x580bb342 vgPlain_amd64_linux_REDIR_FOR_strlen
--19499--     new: 0x04023890 (strlen              ) R-> (2007.0) 0x048448d0 strlen
--19499-- REDIR: 0x4020070 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4845730 (strcmp)
--19499-- REDIR: 0x4023df0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x48491a0 (mempcpy)
--19499-- Reading syms from /usr/lib/libc-2.33.so
--19499-- REDIR: 0x490a0b0 (libc.so.6:memmove) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
==19499== Preferring higher priority redirection:
--19499--     old: 0x049dd510 (__memcpy_avx_unalign) R-> (2018.0) 0x04846980 __memcpy_avx_unaligned_erms
--19499--     new: 0x049dd510 (__memcpy_avx_unalign) R-> (2018.1) 0x04848220 memmove
--19499-- REDIR: 0x49095b0 (libc.so.6:strncpy) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a3f0 (libc.so.6:strcasecmp) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909050 (libc.so.6:strcat) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909610 (libc.so.6:rindex) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490b7a0 (libc.so.6:rawmemchr) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x49237f0 (libc.so.6:wmemchr) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4923330 (libc.so.6:wcscmp) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a210 (libc.so.6:mempcpy) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a040 (libc.so.6:bcmp) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909540 (libc.so.6:strncmp) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909100 (libc.so.6:strcmp) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a180 (libc.so.6:memset) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x49232f0 (libc.so.6:wcschr) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x49094a0 (libc.so.6:strnlen) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x49091e0 (libc.so.6:strcspn) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a440 (libc.so.6:strncasecmp) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909180 (libc.so.6:strcpy) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a590 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4924a40 (libc.so.6:wcsnlen) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4923370 (libc.so.6:wcscpy) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909650 (libc.so.6:strpbrk) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x49090b0 (libc.so.6:index) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909460 (libc.so.6:strlen) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490fc10 (libc.so.6:memrchr) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a490 (libc.so.6:strcasecmp_l) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a000 (libc.so.6:memchr) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4923440 (libc.so.6:wcslen) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x4909770 (libc.so.6:strspn) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a390 (libc.so.6:stpncpy) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a330 (libc.so.6:stpcpy) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490b7e0 (libc.so.6:strchrnul) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x490a4e0 (libc.so.6:strncasecmp_l) redirected to 0x48331b0 (_vgnU_ifunc_wrapper)
--19499-- REDIR: 0x49da330 (libc.so.6:__strrchr_avx2) redirected to 0x4844310 (rindex)
--19499-- REDIR: 0x49da500 (libc.so.6:__strlen_avx2) redirected to 0x48447b0 (strlen)
--19499-- REDIR: 0x4905320 (libc.so.6:malloc) redirected to 0x483e750 (malloc)
==19499== Conditional jump or move depends on uninitialised value(s)
==19499==    at 0x1091F9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499==  Uninitialised value was created by a heap allocation
==19499==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19499==    by 0x1091C9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499== 
--19499-- REDIR: 0x49da140 (libc.so.6:__strchrnul_avx2) redirected to 0x4848ca0 (strchrnul)
==19499== Conditional jump or move depends on uninitialised value(s)
==19499==    at 0x48447C8: strlen (vg_replace_strmem.c:469)
==19499==    by 0x48E6FD7: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==19499==    by 0x48D22DE: printf (in /usr/lib/libc-2.33.so)
==19499==    by 0x109092: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499==  Uninitialised value was created by a heap allocation
==19499==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19499==    by 0x1091C9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499== 
--19499-- REDIR: 0x49dd4f0 (libc.so.6:__mempcpy_avx_unaligned_erms) redirected to 0x4848db0 (mempcpy)
--19499-- REDIR: 0x4905980 (libc.so.6:free) redirected to 0x4841120 (free)
==19499== 
==19499== HEAP SUMMARY:
==19499==     in use at exit: 11 bytes in 1 blocks
==19499==   total heap usage: 2 allocs, 1 frees, 1,035 bytes allocated
==19499== 
==19499== Searching for pointers to 1 not-freed blocks
==19499== Checked 94,736 bytes
==19499== 
==19499== 11 bytes in 1 blocks are definitely lost in loss record 1 of 1
==19499==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19499==    by 0x1091C9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499== 
==19499== LEAK SUMMARY:
==19499==    definitely lost: 11 bytes in 1 blocks
==19499==    indirectly lost: 0 bytes in 0 blocks
==19499==      possibly lost: 0 bytes in 0 blocks
==19499==    still reachable: 0 bytes in 0 blocks
==19499==         suppressed: 0 bytes in 0 blocks
==19499== 
==19499== ERROR SUMMARY: 8 errors from 3 contexts (suppressed: 0 from 0)
==19499== 
==19499== 1 errors in context 1 of 3:
==19499== Conditional jump or move depends on uninitialised value(s)
==19499==    at 0x48447C8: strlen (vg_replace_strmem.c:469)
==19499==    by 0x48E6FD7: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==19499==    by 0x48D22DE: printf (in /usr/lib/libc-2.33.so)
==19499==    by 0x109092: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499==  Uninitialised value was created by a heap allocation
==19499==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19499==    by 0x1091C9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499== 
==19499== 
==19499== 6 errors in context 2 of 3:
==19499== Conditional jump or move depends on uninitialised value(s)
==19499==    at 0x1091F9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499==  Uninitialised value was created by a heap allocation
==19499==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19499==    by 0x1091C9: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x109081: ??? (in /home/tushar/Desktop/main)
==19499==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19499== 
==19499== ERROR SUMMARY: 8 errors from 3 contexts (suppressed: 0 from 0)

输出:

$ ./main HelloWorld
'HeloWrd'

释放后:

==19709== HEAP SUMMARY:
==19709==     in use at exit: 0 bytes in 0 blocks
==19709==   total heap usage: 2 allocs, 2 frees, 1,035 bytes allocated
==19709== 
==19709== All heap blocks were freed -- no leaks are possible
==19709== 
==19709== ERROR SUMMARY: 7 errors from 2 contexts (suppressed: 0 from 0)
==19709== 
==19709== 1 errors in context 1 of 2:
==19709== Conditional jump or move depends on uninitialised value(s)
==19709==    at 0x48447C8: strlen (vg_replace_strmem.c:469)
==19709==    by 0x48E6FD7: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==19709==    by 0x48D22DE: printf (in /usr/lib/libc-2.33.so)
==19709==    by 0x1090A2: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19709==  Uninitialised value was created by a heap allocation
==19709==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19709==    by 0x1091D9: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x10908E: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19709== 
==19709== 
==19709== 6 errors in context 2 of 2:
==19709== Conditional jump or move depends on uninitialised value(s)
==19709==    at 0x109209: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x10908E: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19709==  Uninitialised value was created by a heap allocation
==19709==    at 0x483E7C5: malloc (vg_replace_malloc.c:380)
==19709==    by 0x1091D9: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x10908E: ??? (in /home/tushar/Desktop/main)
==19709==    by 0x48A1B24: (below main) (in /usr/lib/libc-2.33.so)
==19709== 
==19709== ERROR SUMMARY: 7 errors from 2 contexts (suppressed: 0 from 0)

【问题讨论】:

  • 你试过在printf("'%s'\n", buff);之后调用free(buffer);吗?
  • 但我从未使用 malloc、calloc 或 realloc 分配 buff。那么,我为什么要释放它。
  • void free(void *__ptr) 释放由 malloc'、realloc' 或 `calloc' 分配的块。文件:stdlib.h
  • 是的,你做到了:char *set_char = (char *)malloc((sizeof(char) * len) + 1); ... return set_char;。这就是buff 的设置。这很简单——每个malloc 都应该有一个free。您的代码中有多少个malloc 调用以及有多少个free 调用?
  • sizeof(char) 定义为 1。

标签: c memory-leaks valgrind


【解决方案1】:

to_set() 中,您为set_char 分配内存,随后您将其返回给调用者。调用者,在本例中为 main() 现在必须释放它以避免泄漏:

        char *buff = to_set(argv[1]);
        printf("'%s'\n", buff);
        free(buff);

【讨论】:

  • 如果您有其他问题,请提出新问题。如果你这样做,我建议你对输入进行硬编码,这样它比交互式程序更容易重现。
猜你喜欢
  • 1970-01-01
  • 2011-01-26
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多