Няшная / Говнокод #25526 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
#include <stdio.h>
#include <stdlib.h>

void myfree(void *ptr)
{
  printf("%p\n", *(void **)ptr);
  free(*(void **)ptr);
  printf("freed!\n");
}

int main(void) {
  char *x __attribute__ (( cleanup (myfree)  )) = malloc(1);
  printf("%p\n", x);
  return 0;
}

https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html

cleanup (cleanup_function)

The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.

If -fexceptions is enabled, then cleanup_function is run during the stack unwinding that happens during the processing of the exception. Note that the cleanup attribute does not allow the exception to be caught, only to perform an action. It is undefined what happens if cleanup_function does not return normally.

Запостил: j123123 j123123, (Updated )

Комментарии (28) RSS

    • Мы кастуем void * в void ** а потом разыменовываем. Это чтоб получить значение самого x а не указателя на него
      Ну т.е. в функцию void myfree(void *ptr) передается указатель на x. Можно переписать как-нибудь вот так:
      void myfree(char **ptr)
      {
        printf("%p\n", *ptr);
        free(*ptr);
        printf("freed!\n");
      }
      Ответить
        • В cleanup_function передаётся указатель на переменную с которой надо что-то сделать. Каст в void** тут для того, чтобы разыменовать и получить значение этой переменной.
          Ответить
          • free(*(void **)ptr)
            Мы же не передаем значение указателя в free, мы передаем указатель.
            Ответить
            • Смотри, x имеет тип char*, память под массив выделяется маллокой, он возвращает указатель на блок памяти, этот указатель мы записываем в x, в myfree передаётся не само значение x(не сам указатель), а указатель на него (указатель на указатель), т.е. чтобы получить значение x надо извлечь указатель по адресу, который передали в функцию.
              Ответить
          • Хрень какая-то получается. j123123, где в доках написано, что в myfree передаётся &x, а не x?
            Ответить
              • А, тьфу, точно же, тип переменной-то у нас — «char *».
                Ответить
    • https://wandbox.org/permlink/fkHNkmWBrnZ06Wuq

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      // https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
      #define MK_ARR(type, name, freefunc, ...) \
      type * name __attribute__ (( cleanup (freefunc)  )) = \
      ({  \
        type *m____tmp = malloc( sizeof ( (type[]){__VA_ARGS__} ) ); \
        struct { typeof( (type[]){__VA_ARGS__}  ) arr;} tmpvar = {{__VA_ARGS__}}; \
        memcpy(m____tmp, tmpvar.arr,  sizeof((type[]){__VA_ARGS__}) ); \
        m____tmp; \
      })
      
      void myfree(void *ptr)
      {
        printf("%p\n", *(void **)ptr);
        free(*(void **)ptr);
        printf("freed!\n");
      }
      
      
      
      int main(void) {
        MK_ARR(int, x, myfree, 1, 2, 3);
        printf("%p {%d %d %d}\n", x, x[0], x[1], x[2]);
        return 0;
      }
      Ответить
      • Хотя еще можно впилить проверку, что если malloc вернул NULL

        Или даже сделать чтоб:
        #define MK_ARR(type, name, mallocfunc, freefunc, ...)
        Чтоб кастомный аллокатор
        Ответить
      • https://wandbox.org/permlink/btXuxt1Gk3NENoxy
        Улучшил
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        #define MK_ARR(type, name, mallocfunc, freefunc, ...) \
        type * name __attribute__ (( cleanup (freefunc)  )) = \
        ({  \
          typeof(type) *m____tmp = mallocfunc( sizeof ( (type[]){__VA_ARGS__} ) ); \
          if (m____tmp == NULL) \
          { \
            exit(EXIT_FAILURE); \
          } \
          typeof( (typeof(type)[]){__VA_ARGS__}  ) tmpvar = {__VA_ARGS__}; \
          memcpy(m____tmp, tmpvar,  sizeof((type[]){__VA_ARGS__}) ); \
          m____tmp; \
        })
        
        void myfree(void *ptr)
        {
          printf("freeing %p\n", *(void **)ptr);
          free(*(void **)ptr);
          printf("freed!\n");
        }
        
        int main(void) {
          MK_ARR(int, x, malloc, myfree, 1, 2, 3);
          printf("%p: {%d %d %d}\n", x, x[0], x[1], x[2]);
          return EXIT_FAILURE;
        }
        Ответить
    • тогда компилятор ругнется на то, что у нас в функцию передается char **, но сама функция принимает void **
      Ответить
  • Лень искать в стандарте это.
    Это туда входит?
    Ответить

Добавить комментарий

Переведи на "PHP", guest!

    А не использовать ли нам bbcode?


    8