如何为结构成员正确分配内存?

How to allocate memory for a structure member properly?

问题不言自明。我想实现一个函数,该函数创建一个结构,该结构具有初始容量为.. initial_capacity 和内部一些属性的动态数组。
这是代码:

#include <malloc.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct IntVector {
        int *vector;
        unsigned int capacity;
        unsigned int size;
} IntVector;

IntVector *int_vector_new(size_t initial_capacity) {
        struct IntVector v = {calloc(initial_capacity, sizeof(int)),
                               initial_capacity, 0};
        IntVector* v_ptr = &v;
        return v_ptr;
}

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -v ./debug 是这样说的:

==1713== Memcheck, a memory error detector
==1713== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1713== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1713== Command: ./debug
==1713==
--1713-- Valgrind options:
--1713--    --leak-check=full
--1713--    --show-leak-kinds=all
--1713--    --track-origins=yes
--1713--    -v
--1713-- Contents of /proc/version:
--1713--   Linux version 4.4.0-18362-Microsoft (Microsoft@Microsoft.com) (gcc version 5.4.0 (GCC) ) #476-Microsoft Fri Nov 01 16:53:00 PST 2019
--1713--
--1713-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-avx-avx2-bmi
--1713-- Page sizes: currently 4096, max supported 4096
--1713-- Valgrind library directory: /usr/lib/valgrind
--1713-- Reading syms from /home/altbrace/IntVector/debug
--1713-- Reading syms from /lib/x86_64-linux-gnu/ld-2.27.so
--1713--   Considering /lib/x86_64-linux-gnu/ld-2.27.so ..
--1713--   .. CRC mismatch (computed 1b7c895e wanted 2943108a)
--1713--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.27.so ..
--1713--   .. CRC is valid
--1713-- Reading syms from /usr/lib/valgrind/memcheck-amd64-linux
--1713--   Considering /usr/lib/valgrind/memcheck-amd64-linux ..
--1713--   .. CRC mismatch (computed 41ddb025 wanted 9972f546)
--1713--    object doesn't have a symbol table
--1713--    object doesn't have a dynamic symbol table
--1713-- Scheduler: using generic scheduler lock implementation.
--1713-- Reading suppressions file: /usr/lib/valgrind/default.supp
==1713== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-1713-by-altbrace-on-???
==1713== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-1713-by-altbrace-on-???
==1713== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-1713-by-altbrace-on-???
==1713==
==1713== TO CONTROL THIS PROCESS USING vgdb (which you probably
==1713== don't want to do, unless you know exactly what you're doing,
==1713== or are doing some strange experiment):
==1713==   /usr/lib/valgrind/../../bin/vgdb --pid=1713 ...command...
==1713==
==1713== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==1713==   /path/to/gdb ./debug
==1713== and then give GDB the following command
==1713==   target remote | /usr/lib/valgrind/../../bin/vgdb --pid=1713
==1713== --pid is optional if only one valgrind process is running
==1713==
==1713== error calling PR_SET_PTRACER, vgdb might block
--1713-- REDIR: 0x401f2f0 (ld-linux-x86-64.so.2:strlen) redirected to 0x580608c1 (???)
--1713-- REDIR: 0x401f0d0 (ld-linux-x86-64.so.2:index) redirected to 0x580608db (???)
--1713-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so
--1713--   Considering /usr/lib/valgrind/vgpreload_core-amd64-linux.so ..
--1713--   .. CRC mismatch (computed 50df1b30 wanted 4800a4cf)
--1713--    object doesn't have a symbol table
--1713-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
--1713--   Considering /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so ..
--1713--   .. CRC mismatch (computed f893b962 wanted 95ee359e)
--1713--    object doesn't have a symbol table
==1713== WARNING: new redirection conflicts with existing -- ignoring it
--1713--     old: 0x0401f2f0 (strlen              ) R-> (0000.0) 0x580608c1 ???
--1713--     new: 0x0401f2f0 (strlen              ) R-> (2007.0) 0x04c32db0 strlen
--1713-- REDIR: 0x401d360 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c33ee0 (strcmp)
--1713-- REDIR: 0x401f830 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c374f0 (mempcpy)
--1713-- Reading syms from /lib/x86_64-linux-gnu/libc-2.27.so
--1713--   Considering /lib/x86_64-linux-gnu/libc-2.27.so ..
--1713--   .. CRC mismatch (computed b1c74187 wanted 042cc048)
--1713--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so ..
--1713--   .. CRC is valid
--1713-- REDIR: 0x4edac70 (libc.so.6:memmove) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9d40 (libc.so.6:strncpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edaf50 (libc.so.6:strcasecmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9790 (libc.so.6:strcat) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9d70 (libc.so.6:rindex) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edc7c0 (libc.so.6:rawmemchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edade0 (libc.so.6:mempcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edac10 (libc.so.6:bcmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9d00 (libc.so.6:strncmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9800 (libc.so.6:strcmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edad40 (libc.so.6:memset) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ef80f0 (libc.so.6:wcschr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9ca0 (libc.so.6:strnlen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9870 (libc.so.6:strcspn) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edafa0 (libc.so.6:strncasecmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9840 (libc.so.6:strcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edb0e0 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9da0 (libc.so.6:strpbrk) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed97c0 (libc.so.6:index) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ed9c70 (libc.so.6:strlen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ee46c0 (libc.so.6:memrchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edaff0 (libc.so.6:strcasecmp_l) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edabe0 (libc.so.6:memchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4ef8eb0 (libc.so.6:wcslen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4eda050 (libc.so.6:strspn) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edaf20 (libc.so.6:stpncpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edaef0 (libc.so.6:stpcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edc7f0 (libc.so.6:strchrnul) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4edb040 (libc.so.6:strncasecmp_l) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--1713-- REDIR: 0x4fca3c0 (libc.so.6:__strrchr_avx2) redirected to 0x4c32730 (rindex)
--1713-- REDIR: 0x4ed6030 (libc.so.6:calloc) redirected to 0x4c31a70 (calloc)
--1713-- REDIR: 0x4ed3950 (libc.so.6:free) redirected to 0x4c30cd0 (free)
==1713==
==1713== HEAP SUMMARY:
==1713==     in use at exit: 20 bytes in 1 blocks
==1713==   total heap usage: 1 allocs, 0 frees, 20 bytes allocated
==1713==
==1713== Searching for pointers to 1 not-freed blocks
==1713== Checked 69,336 bytes
==1713==
==1713== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1713==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1713==    by 0x1086F2: int_vector_new (IntVector.c:13)
==1713==    by 0x1086BB: main (main.c:8)
==1713==
==1713== LEAK SUMMARY:
==1713==    definitely lost: 20 bytes in 1 blocks
==1713==    indirectly lost: 0 bytes in 0 blocks
==1713==      possibly lost: 0 bytes in 0 blocks
==1713==    still reachable: 0 bytes in 0 blocks
==1713==         suppressed: 0 bytes in 0 blocks
==1713==
==1713== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==1713== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

如您所见,我已经连续三个小时尝试修复此问题,但没有任何进展。
希望得到您的帮助。

函数

IntVector *int_vector_new(size_t initial_capacity) {
        struct IntVector v = {calloc(initial_capacity, sizeof(int)),
                               initial_capacity, 0};
        IntVector* v_ptr = &v;
        return v_ptr;
}

returns 指向像

这样声明的局部变量的指针
struct IntVector v

因此在退出函数后指针具有无效值,因为指向的对象不再存在。

动态分配一个结构类型的对象和return指向 分配的内存。或者 return 对象 v 本身通过值传递给函数的调用者。

例如

IntVector int_vector_new(size_t initial_capacity) {
        struct IntVector v = {calloc(initial_capacity, sizeof(int)),
                               initial_capacity, 0};
        return v;
}

IntVector * int_vector_new(size_t initial_capacity) {
        struct IntVector* v_ptr = malloc( sizeof( struct IntVentor ) );

        v_ptr->vector = calloc( initial_capacity, sizeof(int));
        v_ptr->capacity = initial_capacity;
        v_ptr->size = 0;
        return v_ptr;
}

可以添加检查内存是否分配成功

我不知道可能发生的一切,因为目前您没有任何代码显示它的调用位置,但我发现了一个大问题。您正在返回指向在 int_vector_new 中创建的值的指针,因此一旦该函数 returns 指向 (v) 的局部变量将消失。

您可以像这样为 v 分配内存:IntVector* v = malloc(sizeof(IntVector));.

然后使用 -> 语法设置每个字段。像这样:

IntVector* v = malloc(sizeof(IntVector));
v->vector = calloc(initial_capacity, sizeof(int));
v->capacity = initial_capacity;
v->size = 0;

return v;

由于 valgrind 抱怨泄漏,我猜你稍后不会在你的代码中释放 vector。释放将解决有关泄漏内存的投诉。一旦您使用 malloc 分配 v,您将需要释放任何 int_vector_new returns.

的值