Как правильно выделить память для члена структуры? - PullRequest
1 голос
/ 26 февраля 2020

Вопрос довольно очевиден. Я хочу реализовать функцию, которая создает структуру с динамическим c массивом начальной емкости .. 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)

Я пытался исправить это в течение трех часов без какого-либо прогресса, как вы можете видеть.
Надеюсь на вашу помощь.

Ответы [ 2 ]

3 голосов
/ 26 февраля 2020

Функция

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;
}

возвращает указатель на локальную переменную, объявленную как

struct IntVector v

Поэтому после выхода из функции указатель имеет недопустимое значение, поскольку указанный объект не является живым больше.

Либо выделите объект типа структуры динамически и верните указатель на выделенную память. Или верните сам объект 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;
}

Вы можете добавить проверку, является ли память был успешно распределен.

0 голосов
/ 26 февраля 2020

Я не знаю всего, что может происходить, потому что на данный момент у вас нет кода, показывающего, как это называется, но я вижу большую проблему. Вы возвращаете указатель на значение, созданное в int_vector_new, поэтому, как только эта функция вернет локальную переменную, указанную на (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.

...