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

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
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
// http://p99.gforge.inria.fr/p99-html/group__flexible.html

//C99 allows a flexible array member to be defined as the last member of a struct,
// namely an array of undetermined length.
//P99_DECLARE_STRUCT(package_head);

struct package_head {
  char name[20];
  size_t len;
  uint64_t data[];
};

// Such a struct can then be allocated on the heap with a suitable size such 
// that the field data has as many elements as fit in the allocated space from
// the start of data onward. Usually one would allocate such struct with

package_head *a = malloc(sizeof(package_head) + 10 * sizeof(uint64_t));
package_head *b = malloc(sizeof(*b) + 12 * sizeof(b->data[0]));

// This has several disadvantages. Firstly, the syntax is clumsy. We have to
// use a relatively complicated expression that uses two elements of the specification of a or b.

// Secondly, it wastes space. Due to packing of the struct the offset of data "inside"
//  the struct may be less than sizeof(package_head). In most cases the real size
// of the object that we want to construct is

offsetof(package_head, data) + N * sizeof(uint64_t)

// so we are wasting

sizeof(package_head) - offsetof(package_head, data)

// bytes.

// The above formula for the exact size is only valid for larger values of N. We must
// also ensure that we allocate at least sizeof(package_head) bytes. So the complete
// formula looks something like

#define P99_FSIZEOF(T, F, N) P99_MAXOF(sizeof(T), offsetof(T, F) + P99_SIZEOF(T, F[0]) * N)

// which is probably not something that you want to write on a daily basis.

// We provide several interfaces to allocate struct with flexible members

Херню написали какую-то. Забыли самое главное : нельзя так в лоб аллоцировать память под структуры. Потому что выравнивание может не то быть.
Надо использовать http://man7.org/linux/man-pages/man3/aligned_alloc.3.html

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

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

      • Я в какой-то библиотеке для «Трубопаскакаля» видел самодельные aligned_alloc, aligned_realloc, aligned_free. Там всё было сделано через жопу ООП: память выделялась средствами стандартной библиотеки, оригинальный указатель сохранялся в приватном поле объекта (чтобы можно было делать realloc и free), а функция aligned_alloc возвращала выровненный указатель.
        Ответить
        • А можно было просто возвращать выровненный указатель, только еще выделять место для хранения исходного перед выровненным блоком (ну или один байт смещения).
          Ответить
    • A previous call to free or realloc that deallocates a region of memory synchronizes-with a call to aligned_alloc that allocates the same or a part of the same region of memory. This synchronization occurs after any access to the memory by the deallocating function and before any access to the memory by aligned_alloc. There is a single total order of all allocation and deallocation functions operating on each particular region of memory.

      Т.е. realloc не дурак.
      Ответить
  • Емнип, по стандарту и обычный malloc достаточно ровный для всех примитивов. Для SSE разве что может не хватить.
    Ответить
      • Мне интересно, если я молокой выделю, например, байт, то вся память от этого бата до следующего выровненного адреса зашкварится и молока её никому не отдаст при следующих выделениях?
        Ответить
      • Кстати, а имеет ли право маллок юзать плотные пулы для мелочи?

        Если у меня структура весит 5 байт, то в ней может таиться dword, т.е. начало должно быть выровнено хотя бы на 4?
        Ответить
  • 10 это размер data?
    struct package_head {
      char name[20]; //20 байт
      size_t len; //8 байт
      uint64_t data[]; //8 байт (флексанутый массив же размером 1?)
    };

    20 + 8 + 8 + 10 = 46, и правда не очень выровнено

    В VC нету никаких "Flexible Arrays" (потому что нету С99, а есть ли они в С++ я не знаю) именно потому я за "Microsoft"
    Ответить
    • > флексанутый массив же размером 1?
      Мне кажецца что нуль должно быть, не зря же можно ещё и huint64_t data[0]. Но гцц молчит как пармизан:
      error: invalid application of ‘sizeof’ to incomplete type ‘struct petux’
      Ответить
      • Надо так:
        #include <stdio.h>
        int main() {
            struct Kooryatnik { int petux; int kooritsy[]; } kooryatnik;
            printf("%d", sizeof(kooryatnik)); // 4, проверь
        }
        значится, что 0
        Ответить

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

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

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


    8