- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
calculateSomething(int n){
float* x = new float[n];
/*do smth*/
if ( /*validation*/ ) {
delete[] x;
return;
}
float* y = new float[n];
/*do smth*/
if ( /*validation*/ ) {
delete[] x;
delete[] y;
return;
}
float* z = new float[n];
/*next step*/
if ( /*smth goes wrong*/ ) {
delete[] x;
delete[] y;
delete[] z;
return;
}
/*more calculations with validation*/
delete[] x;
delete[] y;
...
/*more delete[]*/
return;
}
Принципиальная схема говногода, найденного на просторах сети.
bormand 27.06.2012 05:10 # +1
sayidandrtfm 27.06.2012 06:21 # 0
interested 27.06.2012 07:06 # +3
Здесь нужно соблюдать порядок между этими EXIT_ и порядком создания, ошибкоопасно.
Если есть возможность безопасно вызвать free на нулевой, скажем, указатель, то лучше все инициализировать вначале нулями, а в самом конце все освободить, и туда, в конец, бросать из всех неудачных валидаторов. Хотя код всё же придётся менять в двух местах, но уже не по всей функции.
bormand 27.06.2012 07:12 # +1
Конечно есть.
Вы правы - лучше сделать одну метку, после которой стоит пачка free.
vistefan 27.06.2012 11:16 # 0
bormand 27.06.2012 12:22 # +1
sayidandrtfm 27.06.2012 11:29 # −1
Программирование на С вообще достаточно опасное занятие.
Но мы ведь не боимся трудностей, правда?
>Если есть возможность безопасно вызвать free на нулевой, скажем, указатель
то лучше все инициализировать вначале нулями
$ man 3 malloc
…
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
…
The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable. On error, these functions return NULL. NULL may also be returned by a successful call to malloc() with a size of zero, or by a successful call to calloc() with nmemb or size equal to zero.
…
Если вы обратили внимание переход по меткам осуществляется в порядке обратном выделению памяти. т. е. если происходит переход на EXIT_Y, то это значит, что код
по Х -ветке отработал успешно(понятно что в в этом упрощённом примере, не принимается во внимание действия м/у выделением памяти и некой валидацией, хотя что там ещё может быть, как не проверка валидности выделенной памяти — не знаю).
interested 27.06.2012 12:27 # 0
А мало ли что ещё может взбрести в голову программистам, которые и в простом случае, да ещё и на C++ умудряются такое выдать.
bormand 27.06.2012 12:31 # +1
HaskellGovno 27.06.2012 12:56 # +2
Вот в таком виде это действительно будет работать. При этом не обязательно использовать malloc free, а можно и new[]/delete[].
interested 27.06.2012 13:00 # −2
HaskellGovno 27.06.2012 13:02 # 0
bormand 27.06.2012 13:03 # +1
> При этом не обязательно использовать malloc free
Я предполагал, что это С. А на с++ ни к чему эти извраты.
sayidandrtfm 27.06.2012 13:10 # 0
Их NULL'ами инициализирует malloc() , в случаи фейла.
HaskellGovno 27.06.2012 16:31 # 0
Не инициализирует, если выполнение туда не дойдет.
bormand 27.06.2012 17:22 # 0
HaskellGovno 27.06.2012 19:30 # 0
bormand 27.06.2012 19:34 # 0
sayidandrtfm 27.06.2012 17:30 # +1
В случае с одной меткой, освобождение будут проходить все ресурсы
вне зависимости от того были ли они использованы при попытке выделения памяти или нет.
В случае с множественными метками, освобождение будут проходить только те
ресурсы, которые на момент не прохождения валидации одним из ресурсов
были инициализированы, а также сам ресурс(на ктором malloc() обфейлился, но инициализировал его NULL'ом).
defecate-plusplus 27.06.2012 07:26 # 0
для наглядности можно параллельно иметь enum с говорящими именами
в случае ошибки из всех мест делается единый goto cleanup
а там уже делается switch (runlevel) с кейсами последовательно от максимального значения до 1 без брейков
bormand 27.06.2012 08:04 # +2
А ваш способ с runlevel он, скорее, для ресурсов типа файлов и сокетов.
Еще вариант для С, которым я пользовался - заполняем переменные NULLами (или -1 если у нас файлы или сокеты), при ошибке прыгаем на cleanup, где для всех не NULL'овых (не -1) переменных вызываем соответствующую функцию освобождения ресурса.
Плюс - хорошая развязка между кодом, который получает ресурсы, и кодом, который их освобождает (не надо поддерживать runlevel или писать дополнительные метки, не имеет значения порядок получения ресурсов).
Минус - немного медленнее, порядок освобождения может не совпасть с порядком получения.
TarasB 27.06.2012 10:13 # +4
defecate-plusplus 27.06.2012 11:49 # −2
странно, Тарас, не правда ли?
TarasB 27.06.2012 13:00 # +3
defecate-plusplus 27.06.2012 13:01 # −1
повзрослей уже
TarasB 27.06.2012 13:23 # +4
defecate-plusplus 27.06.2012 13:25 # +5
за логами сколько у меня аккаунтов на гк - к страйкеру
боюсь, ответ тебя удивит
TarasB 27.06.2012 14:29 # +2
bormand 27.06.2012 13:31 # +4
eth0 27.06.2012 13:41 # +2
roman-kashitsyn 27.06.2012 13:37 # +6
defecate-plusplus 27.06.2012 13:41 # +7
TarasB 27.06.2012 13:51 # +1
sayidandrtfm 27.06.2012 14:10 # +3
rat4 27.06.2012 14:14 # +6
vistefan 27.06.2012 13:31 # +7
Ребята, зачем усложнять себе жизнь?
Тарас, ходят слухи, что у тебя баттхёрты по поводу минурастов. Искренне, скорейшего выздоровления тебе.
eth0 27.06.2012 13:44 # +4
P.S. В говнокоде++ хочу возможность переголосовать в течение некоторого времени. И разнести чёртовы кнопочки.
vistefan 27.06.2012 16:04 # +3
bormand 27.06.2012 16:19 # +1
eth0 27.06.2012 17:03 # +1
bormand 27.06.2012 17:24 # +2
vistefan 27.06.2012 18:06 # +1
Это воистину худший вариант. Даже просто голый текст - и то лучше...
bormand 27.06.2012 18:16 # 0
eth0 27.06.2012 20:01 # +4
bormand 27.06.2012 20:06 # +7
eth0 27.06.2012 21:05 # +4
Ещё можно хвалиться, у кого код наиболее говняный. Особые мастера могут написать ридер на баше.
vistefan 27.06.2012 18:05 # 0
bormand 27.06.2012 18:18 # 0
vistefan 27.06.2012 18:27 # +3
[offtop]Bormand, начинает казаться, что вы смайлофажите.[/offtop]
bormand 27.06.2012 18:38 # +2
Ага, на закуску к пиву.
[offtop]Кто смайлофаг ;) Я ;) Как вы это определили? )))[/offtop]
Lure Of Chaos 27.06.2012 20:24 # +3
TarasB 27.06.2012 20:42 # +1
Lure Of Chaos 27.06.2012 20:49 # +1
sayidandrtfm 27.06.2012 11:39 # 0
По сути - тоже самое, но в профиль.
Про ресурсоёмкость не пишу, ибо компиляторы нынче шибко умные пошли.
defecate-plusplus 27.06.2012 11:43 # 0
goto хейтеры довольны
TarasB 27.06.2012 13:01 # 0
defecate-plusplus 27.06.2012 13:03 # 0
wtf двойной брейк?
TarasB 27.06.2012 13:16 # 0
defecate-plusplus 27.06.2012 13:23 # +4
start
inner loop
still in one-pass loop
outside
TarasB 27.06.2012 16:55 # 0
defecate-plusplus 27.06.2012 17:13 # 0
в любом случае, всё прекрасно будет работать без goto, если включить голову
TarasB 27.06.2012 18:19 # 0
Выход из двойного цикла иногда нужен именно по алгоритму.
bormand 27.06.2012 18:30 # +2
Флагоебство не нужно, т.к. снижает и наглядность и производительность сильнее чем goto.
defecate-plusplus 27.06.2012 19:39 # 0
TarasB 27.06.2012 19:42 # 0
А выход из двойного цикла - проблема и в С++.
bormand 27.06.2012 19:47 # 0
Скинь, пожалуйста, пример кода, в котором требуется даблбряк (полностью функцию), попробуем что-нибудь сделать с ним.
TarasB 27.06.2012 20:01 # +2
rat4 27.06.2012 20:16 # +3
TarasB 27.06.2012 20:43 # +1
bormand 27.06.2012 20:45 # +7
Убей их. Они слишком много знают.
А если серьезно - если кроме методов класса никто не видит - это уже хорошо.
bormand 27.06.2012 20:21 # +1
Код в студию ;)
HaskellGovno 27.06.2012 20:34 # 0
Локальная функция:
- локальна на функцию.
А также анонимный немспейс:
- локальна на модуль cpp
bormand 27.06.2012 20:40 # 0
http://ideone.com/TzUwa
TarasB 27.06.2012 20:44 # 0
defecate-plusplus 28.06.2012 10:32 # +2
с++03 compartible:
HaskellGovno 28.06.2012 11:08 # 0
Ты чего с аватарки фак показываешь или у виска крутишь?
defecate-plusplus 28.06.2012 11:29 # +1
анализирую
TarasB 28.06.2012 11:17 # +3
roman-kashitsyn 28.06.2012 11:18 # +2
Ада?
defecate-plusplus 28.06.2012 11:27 # +3
расслабься и жди поддержки стандарта
vistefan 29.06.2012 08:36 # +5
Расслабьтесь и попытайтесь получить удовольствие...
HaskellGovno 27.06.2012 20:28 # 0
bormand 27.06.2012 20:30 # +3
HaskellGovno 27.06.2012 20:40 # 0
2)Настоящие сервера, крутящиеся годами (те что пишутся на си) - пишутся так, что каждый запрос обслуживается в отдельном процессе. Так что в atexit для освобождения части ресурсов самое время.
bormand 27.06.2012 20:48 # 0
Не все. Иногда запросы мелкие и их много.
HaskellGovno 27.06.2012 20:52 # +1
Но тогда, они и годами не крутятся или очень простые или опять же пишутся годами.
vistefan 29.06.2012 08:31 # +3
interested 29.06.2012 08:58 # −1
При множественном break; последующие просто не достигаются.
На первом же выскакивает из цикла, а остальные не у дел, как код после return;
И continue тоже не достигается. Как встретился, так цикл продолжился, а следующий не успевает исполниться.
Т.е. нужен какой-то дополнительный оператор. break в метку или break(<количество вложений>); как-то так.
vistefan 29.06.2012 09:09 # +4
Вопрос был риторическим, как очередное доказательство неправильности суждений @TarasB о брэйках.
interested 29.06.2012 09:22 # 0
bormand 29.06.2012 09:52 # +2
interested 29.06.2012 10:31 # −3
Карма, она не на сервере, она в голове.
bormand 29.06.2012 11:03 # +5
TarasB 29.06.2012 12:02 # 0
eth0 29.06.2012 13:13 # 0
interested 29.06.2012 13:15 # −1
TarasB 29.06.2012 09:25 # +1
vistefan 29.06.2012 09:28 # 0
TarasB 29.06.2012 12:02 # +1
Хотя бывает и специально: http://www.gamedev.ru/code/forum/?id=139163
HaskellGovno 29.06.2012 12:53 # +5
rat4 29.06.2012 15:11 # +2
vistefan 29.06.2012 13:02 # +3
Знатный срачелло там, кстати.
TarasB 29.06.2012 13:17 # +2
sayidandrtfm 27.06.2012 13:11 # +1
interested 27.06.2012 06:29 # 0
Разве что там какие-то ограничения на размещение в стеке, но тогда сразу должна была прийти мысль, о захвате ресурса другим, уже автоматическим объектом (да RAII).
А тут мы видим, что люди шарашат динамическую память без понятия и компилятор не может им помочь избавиться от лишней работы по написанию delete[]. А если таких вычислительных функций не одна, а десять? Это же какой потенциал для ошибки!
Такой код нужно студентам на лекции показывать :)
bormand 27.06.2012 06:43 # +1
VLA? Они, конечно, удобны, но при невнимательности можно словить stack overflow.
На выбор остаются векторы и scoped_ptr.
> Такой код нужно студентам на лекции показывать :)
Не стоит, выучат же.
rat4 27.06.2012 09:00 # +1
Какой "автоматические массивы"? Поясните мысль.
HaskellGovno 27.06.2012 09:23 # 0
int arr[N] на стеке, как было в С, так в С++ этого точно нет. Если только какое то расширение компилятора.
Ну и в случае POD-типов, как здесь, можно использовать alloca.
В MS VS это _alloca и более правильная _malloca
Сомневаюсь, что это часть стандарта (могу ошибаться), но вроде как поддерживается многими компилями.
interested 27.06.2012 09:54 # 0
int arr[n];
Для C++ это избыточно, но, тем не менее... Это, по крайней мере, уже указывает на то, что программист понимает, что семантика памяти должна быть автоматической. Хотя, всё равно, явные пробелы в познаниях std::
rat4 27.06.2012 10:11 # 0
Ниже уже рассказали, что C++ так не умеет.
interested 27.06.2012 10:38 # 0
Александр Македонский тоже великий полководец, но зачем же стулья ломать?
Зато C умеет, сказали ниже, значит можно отмести версию, что код выше -- это нормально для C.
P.S. Вы не в ту сторону смотрите.
bormand 27.06.2012 10:45 # 0
И чем VLA помогут сделать этот код лучше? У вас есть гарантия, что n достаточно мало и мы не получим stack overflow?
VLA для массивов неконтролируемой длины это зло.
interested 27.06.2012 11:12 # 0
vistefan 27.06.2012 12:02 # +1
То есть вы мужчина
>http://www.govnokod.ru/10569#comment143901
Как бы это помягче спросить...
interested 27.06.2012 12:04 # 0
Чтобы уж вам не спрашивать.
roman-kashitsyn 27.06.2012 12:06 # +6
В виду последних эпичных тредов начал подумывать, не изучить ли c++ по человечески чтобы всех троллить. Но теперь вкрадываются сомнения, стоит ли....
interested 27.06.2012 12:10 # 0
Программистов на С++ гораздо больше. Так что не бойтесь. Изучайте.
Вопрос в том... А нуно ли вам это? Занимаетесь ли вы такими вещами, что вам C++ нужен...
roman-kashitsyn 27.06.2012 12:30 # +2
Несмотря на то, что метапрограммированию в с++ достаточно далеко от того, что можно делать в lisp, подходы всё равно интересны. Да и просто неприятно открывать продвинутый цппшный код и не понимать, что за неведомая х**ня там творится.
Конечно, гораздо больше интереса у меня вызывает функциональное программирование и большие распределённые высоконагруженные системы. Но мой жизненный опыт гласит, что для того, чтобы летать в облаках функциональщины, нужно уметь твёрдо стоять на грешной c/c++ земле. И если с C у меня особых проблем нет, то вот c++ код бывает непонятным довольно часто.
rat4 27.06.2012 13:07 # 0
ромбовидное_наследование.cxx
interested 27.06.2012 13:09 # 0
roman-kashitsyn 27.06.2012 13:10 # 0
interested 27.06.2012 06:45 # 0
В C++ вообще массивы C-style -- это нехорошо. Есть мощная и удобная стандартная библиотека.
bormand 27.06.2012 06:52 # 0
interested 27.06.2012 07:01 # 0
В C наличие таких массивов было бы действительно удобным, а в С++ уже избыточно. При такой-то необъятной стандартной библиотеке!
>Не стоит, выучат же.
Прально! Выучат, что это плохо. Будут пользовать std::
ctm 27.06.2012 07:04 # 0
float* x = new float[n];
...
if (! /*validation*/ ) {
float* y = new float[n];
...
if (! /*validation*/ ) {
...
}
delete[] y;
}
delete[] x;
зы. подразумевается работа без генерации исключений
bormand 27.06.2012 07:09 # 0
Для c++ именно этим и плох.
Кстати, со scoped_ptr код короче, надежнее, понятнее и эквивалентен по производительности.
bormand 27.06.2012 07:18 # 0
interested 27.06.2012 09:58 # +1
HaskellGovno 27.06.2012 11:23 # 0
interested 27.06.2012 13:04 # 0
HaskellGovno 27.06.2012 16:36 # 0
interested 27.06.2012 16:39 # −5
HaskellGovno 28.06.2012 00:05 # +2
interested 28.06.2012 08:53 # −5
interested 27.06.2012 10:14 # 0
Вопрос не только в копипасте большого количества delete[], хотя, предложенный вариант, вне всяких сомнений легче отследить, но и в том, что "ручное" освобождение памяти не нужно. Память имеет автоматическую семантику: точно известно где и когда создать и точно известно, где и когда убрать. Пример, конечно, уж совсем тривиальный, потому что здесь даже не нужно выделять структурных блоков видимости, чтобы делегировать управление вставку вызовов работы с памятью компилятору.
bormand 27.06.2012 10:34 # +1
Нужно. В тех случаях когда скопы, деревья наследования и счетчики ссылок уже не спасают. Ну и, конечно, для реализации всех этих способов освобождения памяти.
interested 27.06.2012 10:58 # 0
Я говорю, про "не нужно" в конкретном примере.
Очень часто люди используют семантику динамической памяти, когда видно, что семантика автоматическая или статическая. Да, технически, приходится прибегать к куче и использовать аллокацию и освобождение памяти, но это можно спрятать, ведь есть возможности ООП по сокрытию технической реализации.
Полагаю, такого не может произойти, что в коде образуется кусок памяти, который невозможно освободить. Существование сборщиков мусора говорит о том, что это возможно. Есть какой-нибудь 1% кода, когда это действительно затруднительно.
Но может быть это просто наша ошибка? Может стоит пересмотреть пост-пред условия контрактов, как-то поменять весь алгоритм, чтобы стало проще? Может мы изначально выбрали неверное архитектурное исполнение?
Здесь масса причин может быть.
По крайней мере, существование сборщиков мусора в управляемых языках показывает, что уборка этого 1% может быть сделана. Причём, зная конкретно структуру свой программы, скорее всего, можно организовать это ещё более эффективно. И всего-то в одном случае из ста. Да и то, это я хватанул. Такие ситуации исчисляются сотыми долями процента и весьма специфичны, для них, наверняка, есть велосипеды.
bormand 27.06.2012 07:07 # −4
HaskellGovno 27.06.2012 07:17 # 0
std::unique_ptr
boost::scoped_array
TarasB 27.06.2012 09:11 # +2
bormand 27.06.2012 09:14 # 0
defecate-plusplus 27.06.2012 09:15 # −1
TarasB 27.06.2012 09:22 # +1
defecate-plusplus 27.06.2012 09:23 # 0
#if defined (WIN32) ...
тебе разве не достаточно
http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
http://www.kernel.org/doc/man-pages/online/pages/man3/alloca.3.html
http://www.opennet.ru/man.shtml?topic=alloca&category=3&russia n=1 // freebsd
bormand 27.06.2012 09:25 # 0
bormand 27.06.2012 09:22 # 0
Но они никому не нужны, т.к. можно без проблем создать класс, пользующийся alloca на мелких N и кучей на больших N. В этом случае имеем профит сопоставимый с VLA на мелких массивах, и не боимся вызвать stack overflow.
P.S. А есть в бусте такой класс?
defecate-plusplus 27.06.2012 09:28 # −1
был в с++11 proposal о dynarray<T>, но вроде как его отклонили
зы. в с++ VLA?
HaskellGovno 27.06.2012 09:34 # 0
Может в буст добавили.
defecate-plusplus 27.06.2012 09:43 # −1
внимательный зритель, кстати, заметит, что аллокация в этом dynarray делается по миссионерски - new char[ n*sizeof(T) ];
фактически, несложно написать свой враппер над alloca, вызывая деструкторы объектов в массиве по выходу из scope, только стек всё равно освободится при выходе из функции
HaskellGovno 27.06.2012 11:29 # 0
Наверное, можно в тех случаях, где поддерживается alloca и n меньше некоторой величины (предлагаю размер страницы для платформ со страничной памятью), то выделяем через alloca на стеке.
HaskellGovno 27.06.2012 09:31 # 0
defecate-plusplus 27.06.2012 09:31 # −1
HaskellGovno 27.06.2012 09:37 # 0
> C (added in C99 as a conditional feature which implementations aren't required to support[1]; on some platforms
bormand 27.06.2012 09:58 # 0
TarasB 27.06.2012 12:59 # 0
bormand 27.06.2012 13:36 # 0
TarasB 27.06.2012 13:41 # 0
При замене T[] на std::vector<T> приходится строки, содержащие
T *t=a заменять на T*t=&a[0];
rat4 27.06.2012 13:52 # +1
bormand 27.06.2012 13:52 # 0
Потому что нехуй.
> T*t=&a[0];
Ужас какой. Можно узнать зачем все это?
TarasB 27.06.2012 13:56 # 0
bormand 27.06.2012 13:59 # 0
std::fill
> скопировать из вектора в видеобуфер
std::copy
TarasB 27.06.2012 14:07 # 0
Кстати, как константныей итератор кастануть в неконстантный?
bormand 27.06.2012 14:10 # +1
Все-таки хочется выстрелить себе в ногу?
HaskellGovno 27.06.2012 16:43 # +3
А вы знаете толк в сортах говна...
rat4 27.06.2012 14:09 # +2
Вектор для хранения картинки плохо подходит: её размер известен и стоит использовать массив.
TarasB 27.06.2012 14:19 # +1
rat4 27.06.2012 14:26 # 0
TarasB 27.06.2012 14:30 # +1
Охуенное решение.
rat4 27.06.2012 14:39 # +2
TarasB 27.06.2012 14:44 # +1
bormand 27.06.2012 14:43 # +2
Как внутренность класса SoftwareSurface - сойдет.
TarasB 27.06.2012 15:06 # 0
bormand 27.06.2012 15:08 # 0
rat4 27.06.2012 15:12 # +1
HaskellGovno 27.06.2012 16:37 # 0
bitblt
fastblt
и тому подобное с аппаратной поддержкой блитинга из памяти в видеопамять
interested 27.06.2012 13:56 # +1
bormand 27.06.2012 14:09 # 0
defecate-plusplus 27.06.2012 14:51 # −1
bormand 27.06.2012 14:58 # +2
defecate-plusplus 27.06.2012 15:09 # 0
я как то привык к студийному stl, что считал за должное - на &v[0] пустого вектора всегда жди беды
а это оказывается _SECURE_SCL мне так всегда подсирает
насчет вменяемого - как раз удобно передавать в сишные вызовы (..., &v[0], v.size(), ...), а там уже пускай библиотека в зависимости от size() пляшет
bormand 27.06.2012 15:35 # 0
А насчет передачи - ничего не имею против. Как я писал ниже "корректный код, зная, что ему передали указатель на массив длины 0 не будет его трогать".
interested 27.06.2012 15:02 # 0
Да ещё и пытаться передавать дырку от бублика куда-то там?
bormand 27.06.2012 15:05 # 0
interested 27.06.2012 15:26 # 0
Но мне чаще встречались такие, которые требуют выполнения предусловий. Корректный указатель, положительное число и т.д.
P.S. Это может быть связано, конечно со сферой именно вычислительной. Функция сама не выполняет никаких проверок, потому что это может снизить производительность. Ведь неизвестно сколько раз её вызовут... 10 или 450 000.
bormand 27.06.2012 15:41 # 0
Проверки предусловий безусловно нужны. Но зачем проверять корректность указателя при size==0? И, кстати, как проверить корректность указателя в не managed куче?
> Функция сама не выполняет никаких проверок, потому что это может снизить производительность.
Я понимаю. Но допустим этой функции передали data=NULL и size==0. Зачем код будет трогать элементы data, если size==0. Можно пример? (Случай, если функция требует массив ненулевого размера отбрасываем, т.к. тогда ошибка не в том, что функции передали мусор в указателе, а в том что size==0).
interested 27.06.2012 15:52 # 0
Передаём два массива double in* double out* и два размера size_t n size_t m
Какой-то массив не определён и один из размеров равен нулю.
Функция не будет думать, что там что-то нулевое, а начнёт обращаться к элементам n*j + i. И будет бум!
Проверить на корректность указатель нельзя никак. Разве что dynamic_cast в некотором роде проверяет корректность указателя. А вообще никак. Операции передачи указателя всегда доверенные. Тот, кто передаёт, должен быть уверен в том, что указатель верный. Обыкновенно он уверен, потому что пред и пост условие содержит правило "указатель верный".
defecate-plusplus 27.06.2012 15:56 # 0
double const * in - только его и можно передать пустым
соответственно его размерности n и m будут в точности = 0, и циклы [0..n), [0..m) не сделают ни одной итерации
double * out - ну так он не имеет права быть меньше in
бум не случится
interested 27.06.2012 15:59 # 0
Меня просили пример, куда приходят некорректные данные, но допускаются нулевые размеры.
defecate-plusplus 27.06.2012 16:01 # +1
interested 27.06.2012 16:04 # 0
Вы забыли инициализировать вектор.
bormand 27.06.2012 16:22 # 0
Ок. Его size = 0. Вне зависимости от того что я передам в функцию - правильный указатель на пустой массив или любую хуйню - произойдет краш. Хотя в случае с правильным указателем он скорее всего не произойдет. Что еще хуже.
interested 27.06.2012 16:34 # −1
defecate-plusplus 27.06.2012 16:44 # +1
зачем ей max(m,n)
обсуждается транспонирование?
interested 27.06.2012 16:49 # 0
interested 27.06.2012 17:06 # −2
Но мне хотелось притянуть так, чтобы и ноль можно было записать.
bormand 27.06.2012 17:25 # +2
interested 27.06.2012 17:35 # −2
Bormand, успокойтесь. Понял уже я, что ты про другой ноль.
Вот чего конкретно хочется вам сказать про столбцы и строки? Что столбцы и строки -- это представление ковариантность-контрвариантность? Возьмите с полки пирожок.
Я просто поражаюсь тому, как умеют местные говорить не по делу.
bormand 27.06.2012 17:49 # +3
Хорошо. Пусть у нас будет особая, мнимая матрица 0*m. Если задача этого требует - пусть будет. Соответственно у этой матрицы нет элементов. Раз у нее нет элементов - лезть к ним нельзя. Иначе UB. Да и никто лезть не будет. Даже если, к примеру, у нас на входе матрица N*N, а на выходе получается (N-1)*(N-1) и N==1 (N==0, конечно, нельзя, выход за область определения). Поэтому я могу передать в качестве данных хоть мусор, хоть валидный указатель хоть NULL. Функция даже не заметит.
interested 27.06.2012 17:58 # 0
С чего это вдруг у мнимой матрицы нет элементов? Элементов у неё m, просто она мнимая.
И уже понятно, что речь шла о валидности предусловия size()==0. Просто по определению: если size()==0 функция на нулевом массиве должна достигать корректного постусловия. Следовательно, не может разименовать указатель, что приведёт к неопределённости. И потому не важно, что это за указатель.
Ясно
bormand 27.06.2012 17:56 # +2
Кажется понял, к чему вы клоните - (0,m) и (n,0) специальные матрицы, у которых данные хранятся так же как и у матриц (1,m) и (n,1), но алгоритм обращается с ними по-другому? Но этот пример вообще не имеет отношения к "А с чего бы вам получать адрес первого элемента пустого массива?". Здесь массив не пуст (за исключением случая m==n==0), в нем есть max(m, n) элементов.
bormand 27.06.2012 16:46 # +1
interested 27.06.2012 16:55 # 0
И тем не менее, пример наглядно показывает, что не всегда можно передать в функцию дырку от бублика и надеяться, что она её проглотит и сможет разрешить.
Как я написал в своём комментарии: это хорошо, если может, но сам я с таким не сталкивался.
bormand 27.06.2012 16:24 # +2
interested 27.06.2012 16:32 # −1
bormand 27.06.2012 16:20 # 0
Я же писал выше "Случай, если функция требует массив ненулевого размера отбрасываем, т.к. тогда ошибка не в том, что функции передали мусор в указателе, а в том что size==0"
bormand 27.06.2012 16:27 # 0
И слава богу, если будет бум, а не вернется неведомая хуйня из неизвестной области памяти.
HaskellGovno 27.06.2012 20:49 # 0
Так по С++11 копирования не будет, если аллокаторы совпадают. O(1)
Так тоже:
И так (но уже даже до стандарта С++11):
bormand 27.06.2012 20:51 # 0
HaskellGovno 27.06.2012 20:53 # 0
bormand 27.06.2012 17:40 # 0
Рассмотрим все случаи, когда дырка от бублика не будет проглочена. (Пусть функция принимает массив переменной длины data и размер size).
1) size == 0 не входит в область определения функции - имеем UB в любом случае, хоть в data дырка от бублика, хоть NULL хоть валидный указатель.
2) size == 0, входит в область определения функции, но функция все равно лезет к элементам data. С вероятностью 146% в этой функции допущена ошибка, и она и при size>0 лезет за границы массива.
3) size == 0 входит в область определения функции, функция не лезет к элементам data, но передает ее другой функции, которая к ним лезет - проблема рекурсивно сводится к первым двум пунктам.
Во всех трех случаях UB присутствует независимо от того передам я туда NULL, валидный указатель или мусор. Причем валидный указатель только усугубляет проблему, и вместо краша программа может выдавать неправильный ответ.
Поэтому спор о том, можно ли передать &a.front() (возвращающий NULL или мусор для пустого вектора) и a.size() в функцию считаю закрытым. Вердикт - можно.
interested 27.06.2012 18:05 # 0
В нём передаются корректные входные параметры скалярного типа и неверный указатель, проверить это невозможно. И получается бум!
Он никак не связан с size()==0.
bormand 27.06.2012 18:16 # +1
guest 29.06.2012 10:03 # 0
TarasB 29.06.2012 12:03 # +1
defecate-plusplus 29.06.2012 12:10 # 0
TarasB 29.06.2012 12:14 # +1
defecate-plusplus 29.06.2012 12:15 # +2
если беспокоишься за засорение пространства имён, попробуй обернуть в анонимный неймспейс
14.3.1 Template type arguments
2. A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall
not be used as a template-argument for a template type-parameter. [Example:
—end example] [Note: a template type argument may be an incomplete type (3.9). ]
в с++11 кое-что могло поменяться по этому поводу
defecate-plusplus 29.06.2012 12:21 # +3
14.3.1 Template type arguments
1 A template-argument for a template-parameter which is a type shall be a type-id.
2 [ Example:
— end example ] [ Note: A template type argument may be an incomplete type (3.9). — end note ]
TarasB 29.06.2012 12:30 # 0
А как сделать такое?
defecate-plusplus 29.06.2012 12:35 # +2
ты хотел, может:
defecate-plusplus 29.06.2012 12:42 # 0
а студия всеядна
TarasB 29.06.2012 12:51 # 0
Да, мне это было надо (чтоб работало в т.ч. и для классов с конструктором с параметраме).
На const& я забил, оно вынуждает писать const в методах класса, просто & плюётся, что это типа нестандартное расширение, а классы, которые я буду у себя передавать, всё равно слишком мелкие, чтобы копирование со стека могло замедлить работу, да и оптимизации компилятора стопудов есть на этот случай.
defecate-plusplus 29.06.2012 12:54 # 0
вряд-ли тебе на самом деле нужно менять временный объект
TarasB 29.06.2012 12:59 # 0
2. Писать const во всех методах не хочу.
ПС поставил плюсик ^_^
defecate-plusplus 29.06.2012 13:08 # 0
ты уж определись, либо ты меняешь объект (тогда ломай голову над корректной передачей необязательного & - подсказка - аналог boost::optional, либо указатель вместо ссылки), либо ты просто к нему обращаешься за чтением - тогда временный объект const & по умолчанию вполне приемлем
TarasB 29.06.2012 13:10 # 0
defecate-plusplus 29.06.2012 13:13 # 0
TarasB 29.06.2012 13:18 # 0
А передавать A() по копии кто мешает-то?
Ёпт, убрал расширения языка из опций, так он ругнулся на скачанный мной из инета stdint.h
c:\Users\TarasB\Documents\Visual Studio Projects\units\stdint.h(247): fatal error C1071: unexpected end of file found in comment
defecate-plusplus 29.06.2012 13:22 # +6
TarasB 29.06.2012 16:03 # 0
bormand 29.06.2012 16:21 # 0
http://ideone.com/cKrSH
Но нахуя?
По & свежесозданный A(1) передавать нет никакого смысла (да и gcc не даст) - т.к. вызывающая функция все равно не сможет им воспользоваться. Если хочешь изменить в функции объект и воспользоваться результатом - опиши его как "A a(1);", а не создавай прямо в вызове.
По значению - тоже нет смысла, т.к. зазря вертим конструкторы - создаем объект, создаем копию, грохаем объект... Компилятор, возможно, додумается выкинуть лишние операции, но не факт.
Свежесозданный объект имеет смысл передавать только по const &.
TarasB 29.06.2012 16:24 # 0
Так что раз можно, то збс
bormand 29.06.2012 16:27 # +3
Эээ, а зачем тогда передавать этот, хм, unit type, в функцию?
defecate-plusplus 29.06.2012 16:32 # +2
а, следовательно, нет никаких тарасо-проблем "ну там же надо const расставлять, а я крутой программист, мне это не нужно"
bormand 29.06.2012 16:52 # 0
Другое дело - если в нем есть виртуальные методы, и Тарас хочет сделать что-то типа такого:
http://ideone.com/Ezw24
defecate-plusplus 29.06.2012 16:57 # +3
в любом случае, раз он собрался передавать как копию, он (вероятно) понимает, что base b = derived; сделает ему копию именно типа base и никакой полиморфизм тут уже работать не будет
и да, где виртуальный деструктор, блеать?
bormand 29.06.2012 17:04 # 0
Все, месяц каторжных работ на асме. Каюсь. (Хотя в этом примере деструкторы все равно отработают не виртуально).
TarasB 29.06.2012 16:58 # 0
defecate-plusplus 29.06.2012 16:59 # 0
попробуй скажи статическому методу const, посмотрим, оценит ли компилятор шутку
TarasB 29.06.2012 17:06 # 0
(на всякий случай - я про конст, говорящий о том, что метод не меняет данные объекта)
И какая разница, статический или динамический?
defecate-plusplus 29.06.2012 17:09 # 0
а для класса понятия const не существует
поэтому компилятор обязательно выдаст тебе ошибку
ну и, несложный вывод, что статический метод можно вызвать не только у константного объекта, но и вообще без объекта
TarasB 29.06.2012 17:13 # 0
defecate-plusplus 29.06.2012 17:16 # 0
TarasB 29.06.2012 17:21 # 0
TarasB 29.06.2012 17:41 # 0
bormand 29.06.2012 17:43 # 0
defecate-plusplus 29.06.2012 17:46 # 0
опять ты за старое
TarasB 29.06.2012 18:00 # +2
bormand 29.06.2012 18:10 # 0
defecate-plusplus 29.06.2012 18:17 # 0
не парься, он уже знает что делать
TarasB 29.06.2012 18:53 # 0
А переголова из-за передачи неиспользуемого this в нестатическую функцию стопудов уберётся.
HaskellGovno 29.06.2012 18:11 # 0
bormand 29.06.2012 18:18 # +1
rat4 29.06.2012 18:29 # +2
Удачной компиляции :-)
TarasB 29.06.2012 18:53 # 0
rat4 29.06.2012 19:06 # 0
main.c: В функции «evil_timeout»:
main.c:89:24: ошибка: параметр «data» не используется [-Werror=unused-parameter]
bormand 29.06.2012 19:21 # +1
Имхо лучше проявлять дисциплинированность, и в более-менее удобные моменты устранять ворнинги, нежели тратить время на бесполезный фикс ворнингов в коде, который минут через 10-15 будет выпилен нахрен или отрефакторен.
TarasB 29.06.2012 19:25 # 0
TarasB 29.06.2012 19:24 # 0
rat4 29.06.2012 19:33 # 0
HaskellGovno 29.06.2012 19:38 # 0
bormand 29.06.2012 19:41 # +3
HaskellGovno 29.06.2012 19:52 # 0
bormand 29.06.2012 20:03 # 0
TarasB 29.06.2012 20:01 # 0
Отсутствие переноса строки после {?
};?
bormand 29.06.2012 20:04 # 0
TarasB 29.06.2012 20:18 # 0
defecate-plusplus 29.06.2012 21:36 # +1
я знаю ворнинг "файл обязан заканчиваться newline"
на днях я так и не поборол его в гцц 3.x в новом проекте - везде где можно уже поставил, все равно где то у него не вяжется
TarasB 29.06.2012 22:01 # 0
Я её не включаю правда.
roman-kashitsyn 29.06.2012 22:11 # 0
У нас в проекте есть Sonar, который занимается такой хернёй, и менеджмент заставляет нас фиксить "неправильно" названные переменные и слишком много условий в ифах. А то, что архитектура в жопе, и код надо рефакторить нахрен, это мало кого волнует.
Lure Of Chaos 29.06.2012 22:28 # 0
помню, я тогда сильно матерился вместо "mixed tabs and spaces" тоже была фатальной ошибкой, ломающей билд.
Lure Of Chaos 29.06.2012 22:14 # 0
И не успокаиваюсь, пока в коде есть warningи.
Можете показывать на меня пальцами, но у меня при сохранении Eclipse не только форматирует код (да-да, мне лень все пробелы, табы выравнивать ручками), но и сам подставляет this. для полей и методов, а для неизменяемых переменных и полей сам пишет final.
TarasB 29.06.2012 22:27 # +2
Lure Of Chaos 29.06.2012 22:32 # 0
roman-kashitsyn 29.06.2012 22:45 # +1
Кстати, пришлось тут поработать в VS 2008 с c# (помнится, студия - давняя гордость дотнетчиков), так вот, Idea мне кажется гораздо более удобной и стабильной (студия регулярно падает в дебаге). В VS по умолчанию даже дифф-тула нет, а плагины для того же свн тормозные и глючные. Походу всё работает до тех пор, пока всё идёт по плану мелкомягких (TFS и т.п.), шаг влево - вправо - расстрел, прыжок на месте - попытка улететь.
Без Resharper на VS вообще смотреть даже не хочется.
[/holywarmode]
Lure Of Chaos 29.06.2012 23:40 # +1
roman-kashitsyn 29.06.2012 22:37 # 0
Говно, но бесплатное и с кучей плагинов. Есть мнение, что IBM просто не способен на производство продуктов, которыми удобно пользоваться.
roman-kashitsyn 29.06.2012 22:32 # 0
Idea сама выравнивает, предлагает упрощать выражения и подсвечивает слишком сложные конструкции (try внутри цикла считает сложной, к примеру, но уж никак не 4 условия в ифе). Даже емакс выравнивает строчку при нажатии Enter или ввода точки с запятой (можно ещё таб нажать, если нужно форсировать выравнивание). Форматирование, кстати, Sonar не ловит, в коде полно вермишели из табов и пробелов.
Lure Of Chaos 29.06.2012 22:33 # 0
TarasB 29.06.2012 16:57 # 0
Ну нету в этом блядском С++ шаблонов, принимающий ФУНКЦИИ в качестве параметров. В Аде вот блин с 83 года есть, а в С++ нету. Поэтому приходится передавать класс.
bormand 29.06.2012 17:02 # 0
Так?
http://ideone.com/RyeWm
TarasB 29.06.2012 17:05 # 0
Компилятор хоть догадаться и заинлайнить сможет? Гарантируется ли?
bormand 29.06.2012 17:08 # 0
Выхлоп гцц на О2:
defecate-plusplus 29.06.2012 17:04 # 0
зачем шаблониться?
если ты хочешь передавать что-нибудь, что имеет operator (), то тебе нужно либо делать функторы (работает в голом с++03), либо boost::function (std::function)
я не знаю что там умеет твой калеченный андроид ндк, но в принципе boost.function/boost.bind полностью инлайновый и должен работать
TarasB 29.06.2012 17:12 # 0
bormand 29.06.2012 17:14 # 0
Тебе такого инлайна мало?!
TarasB 29.06.2012 17:15 # 0
Это не инлайн. Я не очень рублю АТТ синтаксис, но судя по отсутствию скобок, это прямой вызов, а не по указателю, и на том спасибо. Но это не то, что мне надо
bormand 29.06.2012 17:17 # 0
Где ты тут вызов увидел. Гцц превратило std::cout << run<test>(5, 6) в тупо std::cout << 13. Что как бы намекает на инлайн через 2 колена.
TarasB 29.06.2012 17:20 # +1
defecate-plusplus 29.06.2012 17:23 # +1
http://bit.ly/MZmirQ
компилятор оставил тела функций g и f, потому что они должны быть видны в объектнике
а вот более наглядно:
http://bit.ly/LUDOhz
bormand 29.06.2012 17:24 # 0
Да. _ZNSolsEi вроде как он и есть.
bormand 29.06.2012 17:29 # 0
bormand 29.06.2012 13:14 # +3
Вы так говорите, как будто это что-то плохое.
bormand 29.06.2012 12:38 # +1
Ссылка на созданный конструктором объект.
Все параметры шаблона должны разруливаться на этапе компиляции. Так что походу никак. Но может быть defecate-plusplus расскажет что-то, что я не знаю...