- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
#include <iostream>
#include <alloca.h>
#include <stdlib.h>
#include <new>
using namespace std;
int main(void) {
const size_t N = 5+rand()%4;
char* arr = ::new (alloca(N)) char[N]{1,2,3,4};
for(size_t i=0; i<N; ++i)
cout<<(int)arr[i]<<endl;
cout<<"ok";
return 0;
}
LispGovno 18.01.2014 19:48 # +1
bormand 18.01.2014 19:49 # +3
LispGovno 18.01.2014 19:51 # +1
bormand 18.01.2014 20:00 # +1
LispGovno 18.01.2014 20:02 # +1
bormand 18.01.2014 20:07 # +3
LispGovno 18.01.2014 20:08 # +2
bormand 18.01.2014 20:13 # +6
tirinox 18.01.2014 22:45 # +6
TarasB 19.01.2014 12:51 # +2
LispGovno 18.01.2014 19:51 # +1
А как std::dynarray работает?
bormand 18.01.2014 19:54 # +1
After reviewing national body comments to n3690, this library component was voted out from C++14 working paper into a separate Technical Specification. This container is not a part of the draft C++14 as of n3797
P.S. И где там написано, что он обязан выделять буфер на стеке?
LispGovno 18.01.2014 19:58 # +1
> This way, additional optimization opportunities are possible, for example, using stack-based allocation
bormand 18.01.2014 20:02 # +1
Но гарантий никаких :)
LispGovno 18.01.2014 20:07 # +3
Я прикупил кроличью лапку.
bormand 18.01.2014 19:58 # +1
Максимум что получится - std::dyn_array<int> a(alloca(sizeof(int)*N));
Тут нужно больше магии...
LispGovno 18.01.2014 19:59 # +1
bormand 18.01.2014 20:02 # +1
LispGovno 18.01.2014 20:05 # +1
bormand 18.01.2014 20:09 # +1
LispGovno 18.01.2014 20:11 # +1
bormand 18.01.2014 20:17 # +1
Ты упоролся? Покажи мне строчку, в которой alloca() добавили в стандарт крестов.
> Аллокатор пишешь, что в allocate вызывает alloca
Лол. Ну напиши, потестируй.
LispGovno 18.01.2014 20:20 # +1
bormand 18.01.2014 20:27 # +4
В новом стандарте разве есть alloca? Там, судя по всему, даже std::dynarray по пизде пошел. Покажи мне строчку драфта, в которой описана alloca и ее новое поведение.
std::dynarray нельзя реализовать через alloca т.к. выделенная в его конструкторе память сразу же грохнется на выходе из него. А если конструктор все-таки удастся заинлайнить (что, емнип, компиляторы никогда не делают с функциями, в которых есть alloca) - то цикл с std::dynarray будет пожирать стек, т.к. alloca не понимает скопов.
Поэтому для реализации std::dynarray нужна совсем другая магия, и без допилки компилятора ты его не сделаешь.
LispGovno 18.01.2014 20:44 # +1
bormand 18.01.2014 20:44 # +4
Удачи в использовании этой хуйни в цикле, скопам то ты аллоку все равно не научишь ;)
Впрочем, кидай код, мой пукан уже в ожидании... ко-ко-ко
LispGovno 18.01.2014 20:46 # +4
http://ideone.com/eSJ1F5
crastinus 18.01.2014 20:49 # +4
читер ;)
LispGovno 18.01.2014 20:52 # +3
А ты хотел что ли чтобы я ушел с порванным анусом после такого? ;)
Это есть почти во всех компиляторах. Только написать дифайн на разных компилях подставляемый по разному. С введением атрибутов в С++11 впредь появятся стандартные атрибуты для этого.
bormand 18.01.2014 21:00 # +5
Процитирую себя: А если конструктор все-таки удастся заинлайнить (что, емнип, компиляторы никогда не делают с функциями, в которых есть alloca) - то цикл с std::dynarray будет пожирать стек, т.к. alloca не понимает скопов
Короче юзать то можно, как и саму alloca, если понимаешь последствия. Но в стандарте такой хуйне не место, там и без этого UB'ов хватает. Потом будет куча разорванных попок, кричащих "а почему у меня std::dynarray в цикле сегфолтится?".
А еще такую реализацию нельзя юзать на куче или в статике:
http://ideone.com/cEw6Hg
> Модификация компилятора ему видите ли нужна.
Для нормальной реализации - нужна.
LispGovno 18.01.2014 21:07 # +2
LispGovno 18.01.2014 21:09 # +1
В крайнем случае можно создать фрейм стека.
http://ideone.com/j13ahX
bormand 18.01.2014 21:15 # +2
Цикл маловат ;) В каком-нибудь while (true) или просто достаточно большом цикле оно покажет себя с лучшей стороны.
> Да ты же гений. Выделил на стеке когда стека не было!
Ну так std::dynarray по стандарту должен был быть безопасным, и выделять память не на стеке, если объект размещается не на стеке (+ еще одно магическое свойство этого класса, которое потребует поддержки от компилера или рантайма). Где там написано, что я не могу его засунуть в другой класс, или создать в куче, или поюзать в большом цикле?
P.S. Короче теперь я понял, почему этот класс не включили в с++14 и послали нахуй в std::experimental.
LispGovno 18.01.2014 21:29 # +1
http://ideone.com/mkXjpG
Никаких переполнений стека.
bormand 18.01.2014 21:33 # +4
Да я не о том, что это обойти нельзя. Можно конечно.
Я все-таки о том, что абстракция у этого класса течет сплошным потоком... В крестах и так UB'ов полно, а ты еще такое чудо хочешь туда добавить.
А слабо переделать класс так, чтобы я не мог разместить его инстансы в куче или статике? :)
LispGovno 18.01.2014 21:44 # +2
bormand 18.01.2014 22:01 # +2
Вот от такого не спасет :) Абстракция дырявая даже если убить new :(
LispGovno 18.01.2014 22:11 # +3
Это да... :(
Ну это особый контейнер и требует особого отношения, очевидно. Так что
И пугаться нет причины,
Если вы еще мужчины
и знаете кресты
bormand 18.01.2014 22:33 # +5
А что если юзать простой и безопасный вариант? Если размер меньше 10 интов - буфер будет размещен в самом объекте. Если больше - в куче. Всегда жрет 10*sizeof(int) байт, но и пофиг, зато потребление стека всегда детерминировано, адекватно работает со скопами, не требует никаких нестандартных функций и атрибутов, нет ограничений по размещению...
kegdan 19.01.2014 16:35 # +4
аборт
govnomonad 19.01.2014 05:57 # +5
стандарт - для анскильных крестопитухов.
На gcc работает - все нормально
bormand 19.01.2014 08:12 # +1
crastinus 18.01.2014 20:28 # +3
Я писал. Не работает. Хотел заменить std::allocator. Внутри функции allocate выделяет память, а когда выходит из функции удаляет память. Функция возвращает мусор.
LispGovno 18.01.2014 20:01 # +1
Это что там можно словить? Всегда пользовался для оптимизации. Код вылетает редко.
bormand 18.01.2014 20:07 # +1
Можно порвать стек, если массив окажется слишком толстым.
Есть не во всех компиляторах (хотя мне такие не попадались).
Возможны баги с циклами (т.к. она не понимает скопов).
LispGovno 18.01.2014 20:14 # +3
Стек! Порвали стек!
Кукарек, кукарек, кукарек...
LispGovno 18.01.2014 21:11 # +3
bormand 18.01.2014 21:21 # +2
crastinus 18.01.2014 20:29 # +3
http://stackoverflow.com/a/3410689/3083709
Xom94ok 18.01.2014 23:29 # +3
Тред подтолкнул меня нагуглить boost::pool_allocator, который решает обходным путем задачу без дефекации в стек, который не резиновый.
bormand 18.01.2014 23:35 # +1
Xom94ok 18.01.2014 23:41 # 0
bormand 18.01.2014 23:43 # +1
Все-таки пул, имхо, идеален для одиночных небольших объектов, а не для массивов.
guest 18.01.2014 23:47 # +2
Xom94ok 19.01.2014 00:09 # +2
Таким же образом у стека массив тоже забирает непрерывный кусок памяти. К тому же, напомнило: http://govnokod.ru/11495#comment148787
> И будет та же самая фигня, что и с кучей.
Фрагментация, если я правильно понял? Таки да, есть такие проблемы. Если бы std::array или boost::array предоставляли возможность подменить аллокатор, то проблема бы сводилась к написанию аллокатора с аналогичной стеку стратегией выделения памяти из пула. ИМХО это все равно лучше, чем вся эта питушня с alloca. Если б я увидел на работе какой-нибудь "my_super_alloca_array_do_not_touch_magi c" - обиделся бы на всю жизнь, т.к. мне предоставлялась честь прибирать за одним таким изобретателем.
bormand 19.01.2014 00:28 # +2
Да там не только она...
- Надо думать о потокобезопасности пула и терять время на блокировки, если мы не делаем thread-local pool'ы (а если делаем - теряем память).
- У пула повышается сложность освобождения от O(1) до O(n) из-за того, что ему надо сортировать пустые блоки во free list'е (иначе он он пропустит половину подходящих мест под массив).
Короче пул превращается в самую обычную кучу. Разве что изолированную.
> проблема бы сводилась к написанию аллокатора с аналогичной стеку стратегией выделения памяти из пула
Дополнительный thread-local стек? А что, это идея! Только его аллокатором оформлять не стоит, т.к. его будут абузить для других структур и расстраиваться - realloc же возможен только у самого свежего, и удаляться все должно строго в обратном порядке... Имхо лучше отдельный спецкласс под такое.
Пока вижу одну проблему - та же фигня, что и с кодом лиспговна - если такой массив запилить в куче, он испортит всю синхронизацию стеков.
Xom94ok 19.01.2014 00:54 # +2
Хех, о таких вещах я даже не задумывался: код в топике - о "возне" в стеке, а я не представляю себе ситуацию, при которой один поток начинает модифицировать стек другого.
> повышается сложность освобождения от O(1) до O(n)
Пару лет назад я встречал STL-совместимые set и map для диапазонов значений. Я не математик, но мне кажется, что O(n) можно улучшить до O(log n). Ну, это так, догадки. Похоже, я слишком серьезно отнесся к коду, который написан just for lulz :)
bormand 19.01.2014 08:16 # +2
Не-не-не. Сам пул же не в стеке создается, он общий... Вот потоки и подерутся за него.
> можно улучшить до O(log n)
Вполне возможно. Я про конкретную реализацию free list'ов в бустовском пуле. Там прям так и написано - хочешь непрерывные чанки аля массивы - включай сортировку при освобождении и имей O(n).
WGH 19.01.2014 13:00 # +3
bormand 19.01.2014 14:01 # 0
Про идею хомячка обсуждали чуть выше, где я предложил не оформлять его аллокатором, т.к. далеко не все контейнеры адекватно смогут с таким аллокатором работать. А тут я пишу про конкретный бустовский пул...
LispGovno 19.01.2014 13:06 # 0
TarasB 19.01.2014 12:55 # +2
я для такой хуйни стек тупо эмулирую
выделение-освобождение за O(1), ассерты проверяют, чтобы освобождалось строго в обратном порядке
я ради такого даже в своём контейнере в деструкторе порядок уничтожения перевернул
LispGovno 19.01.2014 13:02 # 0
WGH 19.01.2014 13:15 # 0
TarasB 19.01.2014 13:16 # 0
bormand 19.01.2014 14:02 # 0
TarasB 19.01.2014 14:11 # +2
bormand 19.01.2014 14:14 # +1
kegdan 19.01.2014 14:44 # 0
Если я правильно понимаю ++ (а я не понимаю) то порядок значения не имеет?
roman-kashitsyn 19.01.2014 15:01 # +3
Объекты всегда разрушаются в порядке, обратном созданию. И это правильно. Пример:
A a;
B b(a);
b использует a. Если разрушить a до разрушения b, это может помешать нормальному разрушению b, т.к. b может захотеть что-то сделать с a в деструкторе. Аналогично с наследованием: если B наследует A, это реализуется в виде подобъекта a внутри b. Нельзя разрушать внутренности объекта, пока сам объект не разрушен.
kegdan 19.01.2014 15:13 # 0
Если массив линкованный - тогда ясен пень с конца.
bormand 19.01.2014 15:14 # +1
Какой-какой массив?
kegdan 19.01.2014 15:18 # 0
1024-- 19.01.2014 15:26 # +1
kegdan 19.01.2014 15:53 # 0
roman-kashitsyn 19.01.2014 15:39 # +2
crastinus 20.01.2014 18:18 # +1