рд╕рдлрд╛рдИ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛

рдЬреАрд╕реАрд╕реА рдбреЙрдХреНрдпреВрдореЗрдВрдЯреЗрд╢рди рд╕реЗ рдЙрджреНрдзрд░рдг [1]:

рдПрдХ рдлрдВрдХреНрд╢рди рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд▓реАрдирдЕрдк рдПрд╕реЗрдЯ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рддрдм рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдПрдХ рд╡реЗрд░рд┐рдПрдмрд▓ рд╕реНрдХреЛрдк рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗрд╡рд▓ рдСрдЯреЛ рдЪрд░ рдкрд░ рд▓рд╛рдЧреВ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдпрд╛ рд╕реНрдерд┐рд░ рдЪрд░ рдХреЗ рд╕рд╛рде рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░, рдЪрд░ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рд▓реЗрдирд╛ рдЪрд╛рд╣рд┐рдПред рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд░рд┐рдЯрд░реНрди рдорд╛рди, рдпрджрд┐ рдХреЛрдИ рд╣реЛ, рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдпрджрд┐ -fexception рд╡рд┐рдХрд▓реНрдк рд╕рдХреНрд╖рдо рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╕реНрдЯреИрдХ рдЕрдирд╡рд╛рдЙрдВрдб рд╣реЛрдиреЗ рдкрд░ рдХреНрд▓реАрдирдЕрдк_рдлрдВрдХреНрд╢рди рдлрд╝рдВрдХреНрд╢рди рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдЕрдкрд╡рд╛рдж рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рдлрд╛рдИ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЕрдкрд╡рд╛рдж рдирд╣реАрдВ рдкрдХрдбрд╝рддреА рд╣реИ, рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдХреНрд░рд┐рдпрд╛ рдХрд░рддреА рд╣реИред рдпрджрд┐ рдХреНрд▓реАрдирдЕрдк_рдлрдВрдХреНрд╢рди рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рд╡рд╛рдкрд╕ рдирд╣реАрдВ рдЖрддрд╛ рд╣реИ, рддреЛ рд╡реНрдпрд╡рд╣рд╛рд░ рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реИред




рд╕рдлрд╛рдИ рд╡рд┐рд╢реЗрд╖рддрд╛ gcc рдФрд░ clang рд╕рдВрдХрд▓рдХ рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рд╣реИред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдХреНрд▓реАрдирдЕрдк рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреА рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реВрдВрдЧрд╛, рдЬреЛ рдХрд┐ std рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд▓реАрдирдЕрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ :: unique_ptr рдФрд░ std :: share_ptr рдПрдирд╛рд▓реЙрдЧреНрд╕ рд╕реА рдореЗрдВред

рдореЗрдореЛрд░реА рдбреАрд▓реЛрдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рд╕рдлрд╛рдИ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:

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

static void free_int(int **ptr) 
{
    free(*ptr); 
    printf("cleanup done\n");
}

int main()
{
    __attribute__((cleanup(free_int))) int *ptr_one = (int *)malloc(sizeof(int));
    // do something here
    return 0;
}

рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкреНрд░реЛрдЧреНрд░рд╛рдо "рдХреНрд▓реАрдирдЕрдк рдХрд┐рдпрд╛" рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИред рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЪреАрдпрд░реНрд╕ред

рд▓реЗрдХрд┐рди рдПрдХ рджреЛрд╖ рддреБрд░рдВрдд рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ: рд╣рдо рдмрд╕ рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ

__attribute__((cleanup(free_int)))

рдХреНрдпреЛрдВрдХрд┐ рдХреНрд▓реАрдирдЕрдк рд╡рд┐рд╢реЗрд╖рддрд╛ рджреНрд╡рд╛рд░рд╛ рдХрд╣реЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рд╕рдВрдХреЗрддрдХ рдХреЛ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдореБрдХреНрдд рдЪрд░ рдореЗрдВ рд▓реЗ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрд╡рдВрдЯрд┐рдд рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ, рдЕрд░реНрдерд╛рдд, рд╣рдореЗрдВ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдбрдмрд▓ рдкреЙрдЗрдВрдЯрд░ рд▓реЗрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдЖрд╡рд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

static void free_int(int **ptr) 
{
    free(*ptr); 
    ...
}

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдХрд┐рд╕реА рднреА рдЪрд░ рдХреЛ рдореБрдХреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдиреНрд╣реЗрдВ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реНрдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:

static void _free(void *p) {
    free(*(void**) p);
    printf("cleanup done\n");  
}

рдЕрдм рд╡рд╣ рдХрд┐рд╕реА рднреА рд╕рдВрдХреЗрдд рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд╕рдХрддреА рд╣реИред

рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рдЙрдкрдпреЛрдЧреА рдореИрдХреНрд░реЛ рд╣реИ ( рд╕рд┐рд╕реНрдЯрдо рдХреЛрдб рдмреЗрд╕ рд╕реЗ ):

#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func)                 \
        static inline void func##p(type *p) {                   \
                if (*p)                                         \
                        func(*p);                               \
        }                                                       \
        struct __useless_struct_to_allow_trailing_semicolon__

рдЬрд┐рд╕реЗ рдмрд╛рдж рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
#define _cleanup_pclose_ __attribute__((cleanup(pclosep)))

рд▓реЗрдХрд┐рди рд╡рд╣ рд╕рдм рдирд╣реАрдВ рд╣реИред рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИ рдЬреЛ рдЗрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдиреВрдареЗ_ptr рдФрд░ shared_ptr pluses рдХреЗ рдПрдирд╛рд▓реЙрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ: https://github.com/Snaipe/libcsptr

рдЙрдкрдпреЛрдЧ рдХрд╛ рдЙрджрд╛рд╣рд░рдг ([2] рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛):

#include <stdio.h>
#include <csptr/smart_ptr.h>
#include <csptr/array.h>

void print_int(void *ptr, void *meta) {
    (void) meta;
    // ptr points to the current element
    // meta points to the array metadata (global to the array), if any.
    printf("%d\n", *(int*) ptr);
}

int main(void) {
    // Destructors for array types are run on every element of the
    // array before destruction.
    smart int *ints = unique_ptr(int[5], {5, 4, 3, 2, 1}, print_int);
    // ints == {5, 4, 3, 2, 1}

    // Smart arrays are length-aware
    for (size_t i = 0; i < array_length(ints); ++i) {
        ints[i] = i + 1;
    }
    // ints == {1, 2, 3, 4, 5}

    return 0;
}

рд╕рдм рдХреБрдЫ рдЕрджреНрднреБрдд рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ!

рдФрд░ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рдЬрд╛рджреВ рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реИред рдЖрдЗрдП рдЕрдиреВрдареЗ_ptr рд╕реЗ рд╢реБрд░реБрдЖрдд рдХрд░реЗрдВ (рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╕рд╛рдЭрд╛ рдХрд░реЗрдВ):

# define shared_ptr(Type, ...) smart_ptr(SHARED, Type, __VA_ARGS__)
# define unique_ptr(Type, ...) smart_ptr(UNIQUE, Type, __VA_ARGS__)

рдЖрдЗрдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЦрд░рдЧреЛрд╢ рдЫреЗрдж рдХрд┐рддрдирд╛ рдЧрд╣рд░рд╛ рд╣реИ:

# define smart_arr(Kind, Type, Length, ...)                                 \
    ({                                                                      \
        struct s_tmp {                                                      \
            CSPTR_SENTINEL_DEC                                              \
            __typeof__(__typeof__(Type)[Length]) value;                     \
            f_destructor dtor;                                              \
            struct {                                                        \
                const void *ptr;                                            \
                size_t size;                                                \
            } meta;                                                         \
        } args = {                                                          \
            CSPTR_SENTINEL                                                  \
            __VA_ARGS__                                                     \
        };                                                                  \
        void *var = smalloc(sizeof (Type), Length, Kind, ARGS_);            \
        if (var != NULL)                                                    \
            memcpy(var, &args.value, sizeof (Type));                        \
        var;                                                                \
    })

рдЕрдм рддрдХ, рд╕реНрдкрд╖реНрдЯрддрд╛ рдореЗрдВ рд╡реГрджреНрдзрд┐ рдирд╣реАрдВ рд╣реБрдИ рд╣реИ, рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдЗрд╕ рднрд╛рд╖рд╛ рдХреА рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рдкрд░рдВрдкрд░рд╛рдУрдВ рдореЗрдВ рдореИрдХреНрд░реЛрдЬрд╝ рдХрд╛ рдПрдХ рдЬрдВрдмрд▓ рд╣реЛред рд▓реЗрдХрд┐рди рд╣рдо рдкреАрдЫреЗ рд╣рдЯрдиреЗ рдХреЗ рдЕрднреНрдпрд╕реНрдд рдирд╣реАрдВ рд╣реИрдВред рдЙрд▓рдЭрди рдХреЛ рд╣рдЯрд╛рдПрдВ:

define CSPTR_SENTINEL        .sentinel_ = 0,
define CSPTR_SENTINEL_DEC int sentinel_;
...
typedef void (*f_destructor)(void *, void *);

рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХрд░реЗрдВ:

# define smart_arr(Kind, Type, Length, ...)                                 \
    ({                                                                      \
        struct s_tmp {                                                      \
            int sentinel_;                                                  \
            __typeof__(__typeof__(Type)[Length]) value;                     \
            void (*)(void *, void *) dtor;                                  \
            struct {                                                        \
                const void *ptr;                                            \
                size_t size;                                                \
            } meta;                                                         \
        } args = {                                                          \
            .sentinel_ = 0,                                                 \
            __VA_ARGS__                                                     \
        };                                                                  \
        void *var = smalloc(sizeof (Type), Length, Kind, ARGS_);            \
        if (var != NULL)                                                    \
            memcpy(var, &args.value, sizeof (Type));                        \
        var;                                                                \
    })

рдФрд░ рд╕рдордЭрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЛ рдХрд┐ рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдВрд░рдЪрдирд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕реЗрдВрдЯрд┐рдирд▓_ рд╡реЗрд░рд┐рдПрдмрд▓, рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рд░рдгреА (рдкреНрд░рдХрд╛рд░) [рд▓рдВрдмрд╛рдИ], рдПрдХ рдбрд┐рд╕реНрдЯреНрд░рдХреНрдЯрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░, рдЬреЛ рдореИрдХреНрд░реЛ рддрд░реНрдХреЛрдВ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд (...) рднрд╛рдЧ рдореЗрдВ рдФрд░ рдПрдХ рдореЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдкрд╛рд░рд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рддрд░реНрдХреЛрдВ рд╕реЗ рднреА рднрд░рд╛ рд╣реЛрддрд╛ рд╣реИред рдЖрдЧреЗ рдПрдХ рдХреЙрд▓ рд╣реИ

smalloc(sizeof (Type), Length, Kind, ARGS_);

рд╕реНрдорд╛рд▓реЛрдХ рдХреНрдпрд╛ рд╣реИ? рд╣рдореЗрдВ рдХреБрдЫ рдФрд░ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдореИрдЬрд┐рдХ рдорд┐рд▓рддреЗ рд╣реИрдВ (рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреБрдЫ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХрд░ рджрд┐рдпрд╛ рд╣реИ):

enum pointer_kind {
    UNIQUE,
    SHARED,
    ARRAY = 1 << 8
};
//..
typedef struct {
    CSPTR_SENTINEL_DEC
    size_t size;
    size_t nmemb;
    enum pointer_kind kind;
    f_destructor dtor;
    struct {
        const void *data;
        size_t size;
    } meta;
} s_smalloc_args;
//...
__attribute__ ((malloc)) void *smalloc(s_smalloc_args *args);
//...
#  define smalloc(...) \
    smalloc(&(s_smalloc_args) { CSPTR_SENTINEL __VA_ARGS__ })

рдЦреИрд░, рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╣рдо рд╕реА рдХреЛ рдкреНрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВред рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рджрд╕реНрддрд╛рд╡реЗрдЬ рднреА рд╣реИ (рдкрд╡рд┐рддреНрд░ рд▓реЛрдЧ, рдореИрдВ рд╣рд░ рдХрд┐рд╕реА рдХреЛ рдЙрдирд╕реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд▓реЗрдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ): рд╕реНрдореЙрд▓реЛрдХ ()

рдлрд╝рдВрдХреНрд╢рди рдПрд▓реЛрдХреЗрдЯрд░ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдореЙрд▓реЛрдХ (3)) рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рд▓реМрдЯрд╛ рд╣реБрдЖ рд╕реВрдЪрдХ "рд╕реНрдорд╛рд░реНрдЯ" рд╕реВрдЪрдХ рд╣реИред <...> рдпрджрд┐ рдЖрдХрд╛рд░ 0 рд╣реИ, рддреЛ NULL рд╡рд╛рдкрд╕ рдЖ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ nmemb 0 рд╣реИ, рддреЛ smalloc рдХрдо рд╕реЗ рдХрдо рд╕рд╛рдЗрдЬ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдореЗрдореЛрд░реА рдмреНрд▓реЙрдХ рдореЗрдВ рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рдкреЙрдЗрдВрдЯрд░ рд▓реМрдЯрд╛рдПрдЧрд╛, рдФрд░ рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рд╕реНрдХреЗрд▓рд░ рдкреЙрдЗрдВрдЯрд░, рдпрджрд┐ nmemb 0 рдХреЗ рдмрд░рд╛рдмрд░ рдирд╣реАрдВ рд╣реИ, рддреЛ рдХрдо рд╕реЗ рдХрдо рд╕рд╛рдЗрдЬ рдХреЗ рдореЗрдореЛрд░реА рдмреНрд▓реЙрдХ рдХреЗ рд▓рд┐рдП рдкреЙрдЗрдВрдЯрд░ рдХрдо рд╕реЗ рдХрдо nmemb рд▓реМрдЯрд╛ рд╣реИ, рдФрд░ рдкреЙрдЗрдВрдЯрд░ рдЯрд╛рдЗрдк рдПрд░реЗ рдХрд╛ рд╣реИред

рдореВрд▓
┬лThe smalloc() function calls an allocator (malloc (3) by default), such that the returned pointer is a smart pointer. <...> If size is 0, then smalloc() returns NULL. If nmemb is 0, then smalloc shall return a smart pointer to a memory block of at least size bytes, and the smart pointer is a scalar. Otherwise, it shall return a memory block to at least size * nmemb bytes, and the smart pointer is an array.┬╗

рдпрд╣рд╛рдБ рд▓рдШреБ рдХрд╛ рд╕реНрд░реЛрдд рд╣реИ:

__attribute__ ((malloc)) void *smalloc(s_smalloc_args *args) {
    return (args->nmemb == 0 ? smalloc_impl : smalloc_array)(args);
}

рдЖрдЗрдП рдХреЛрдб smalloc_impl рдХреЛ рджреЗрдЦреЗрдВ, рдЕрджрд┐рд╢ рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЖрд╡рдВрдЯрдиред рд╡реЙрд▓реНрдпреВрдо рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рд╛рдЭрд╛ рдкреЙрдЗрдВрдЯрд░реНрд╕ рд╕реЗ рдЬреБрдбрд╝реЗ рдХреЛрдб рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдФрд░ рдЗрдирд▓рд╛рдЗрди рдФрд░ рдореИрдХреНрд░реЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди:

static void *smalloc_impl(s_smalloc_args *args) {
    if (!args->size)
        return NULL;

    // align the sizes to the size of a word
    size_t aligned_metasize = align(args->meta.size);
    size_t size = align(args->size);

    size_t head_size = sizeof (s_meta);
    s_meta_shared *ptr = malloc(head_size + size + aligned_metasize + sizeof (size_t));

    if (ptr == NULL)
        return NULL;

    char *shifted = (char *) ptr + head_size;
    if (args->meta.size && args->meta.data)
        memcpy(shifted, args->meta.data, args->meta.size);

    size_t *sz = (size_t *) (shifted + aligned_metasize);
    *sz = head_size + aligned_metasize;

    *(s_meta*) ptr = (s_meta) {
        .kind = args->kind,
        .dtor = args->dtor,
        .ptr = sz + 1
    };

    return sz + 1;
}

рдпрд╣рд╛рдВ рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЪрд░ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХреА рдЧрдИ рд╣реИ, рд╕рд╛рде рд╣реА s_meta рдХрд╛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╣реЗрдбрд░ рдкреНрд▓рд╕ рдЖрдХрд╛рд░ рдХрд╛ рдПрдХ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреНрд╖реЗрддреНрд░ args-> meta.size рд╢рдмреНрдж рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдЧрдардмрдВрдзрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдПрдХ рдФрд░ рд╢рдмреНрдж (sizeof (tt))ред рдлрд╝рдВрдХреНрд╢рди рдЪрд░ рдХреЗ рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░ рд▓реМрдЯрд╛рддрд╛ рд╣реИ: ptr + head_size + align_metasize + 1.

рдорд╛рди 42 рдХреЗ рд╕рд╛рде рдЖрд░рдВрднреАрдХреГрдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдПрдХ рдЪрд░ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:

smart void *ptr = unique_ptr(int, 42);

рдпрд╣рд╛рдБ рд╕реНрдорд╛рд░реНрдЯ рдПрдХ рдореИрдХреНрд░реЛ рд╣реИ:

# define smart __attribute__ ((cleanup(sfree_stack)))

рдЬрдм рдкреЙрдЗрдВрдЯрд░ рдЧреБрдВрдЬрд╛рдЗрд╢ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ, sfree_stack рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ:

CSPTR_INLINE void sfree_stack(void *ptr) {
    union {
        void **real_ptr;
        void *ptr;
    } conv;
    conv.ptr = ptr;
    sfree(*conv.real_ptr);
    *conv.real_ptr = NULL;
}

рдирд┐: рд╢реБрд▓реНрдХ рд╕рдорд╛рд░реЛрд╣ (рд╕рдВрдХреНрд╖рд┐рдкреНрдд):

void sfree(void *ptr) {
    s_meta *meta = get_meta(ptr);
    dealloc_entry(meta, ptr);
}

Dealloc_entry рдлрд╝рдВрдХреНрд╢рди, рдореВрд▓ рд░реВрдк рд╕реЗ, рдПрдХ рдХрд╕реНрдЯрдо рдбрд┐рд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рд╣рдордиреЗ рдЗрд╕реЗ рдЕрдиреВрдареЗ_ рддрд░реНрдХ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдмрд╕ рдореБрдлреНрдд (рдореЗрдЯрд╛) рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╕реВрддреНрд░реЛрдВ рдХреА рд╕реВрдЪреА:

[1] рдЖрдо рдЪрд░ рдЧреБрдг ред
[реи] GCC рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫрд╛ рдФрд░ рдореБрд╣рд╛рд╡рд░реЗрджрд╛рд░ рддрд░реАрдХрд╛ __attribute __ ((рд╕рдлрд╛рдИ)) рдФрд░ рд╕реВрдЪрдХ рдШреЛрд╖рдгрд╛рдПрдБ ред
[рей] рдЬреАрд╕реАрд╕реА рдореЗрдВ __cleanup__ рдЪрд░ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ ред

All Articles