LINUX.ORG.RU
Ответ на: комментарий от firkax

Но на деле после неё должна быть трассировка всех путей выполнения кода в уме, с проверкой что состояние, которое ты ожидаешь, совпадает с тем, которое получается в ходе трассировки.

Если в программе хотя бы 10 условий, то путей уже 1024.

И, самое главное, никакая проверка в уме не спасает от чего-то типа:

a = malloc(...);

x = malloc(...);

if(!x) {
  .... 
  free(a);
  // забыл return
}

b = malloc(...);
c = malloc(...);

a[42] = 69; // где-то в b или c может быть испортилась память

*b[13] = 0; // а вот здесь уже может быть испортилась память в произвольном месте
...

При чтении будешь всегда совершать ту же ошибку, что и при письме (потому что мысль будет идти по тому же руслу). При тестировании получить NULL от malloc достаточно тяжело, поэтому код обработки ошибки не протестируется.

Иногда спасает чтение другим человеком. Но тоже не всегда. Внимательность ведь не абсолютна.

monk ★★★★★
()
Ответ на: комментарий от firkax

мой софт память не бьёт

«В моем софте багов не бывает» — это в детский сад, пожалуйста.

byko3y ★★★★
()
Ответ на: комментарий от monk

Если в программе хотя бы 10 условий, то путей уже 1024.

Нет, надо инварианты находить и использовать. Ну и писать код так, чтобы их было побольше. Например, если ты делаешь условное

if(x>10) { snprintf(st+l, stsize-l, "x=%u; ", x); l+=strlen(st+l); }

то остаётся инвариант: strlen(st)==l && l<stsize (если он в начале был сделан), а конкретное значение l уже ни на что не влияет (ну, в нормальном коде).

При чтении будешь всегда совершать ту же ошибку, что и при письме

Если читать спустя хотя бы сутки - уже скорее всего нет. Если не помогает - делаешь две итерации, одну через сутки (при коммите, делать его без перепрочтения всех изменений нельзя), вторую через неделю (при крупном мерже новых наработок в прод-ветку).

Иногда спасает чтение другим человеком

Ну и это тоже можно, и даже желательно, если разработчиков больше одного.

При тестировании получить NULL от malloc достаточно тяжело, поэтому код обработки ошибки не протестируется.

Больше того: даже не при тестировании получить NULL от него практически невозможно. Но тут всё очень просто - любой malloc должен быть обёрнут строкой вида

if(!(x = malloc(...))) { }
либо функцией-обёрткой которая никогда не возвращает NULL.

Вот прямо так, в той же строчке. Видишь голый malloc() - видишь ошибку, исключений не допускаешь. Ошибиться при таком подходе очень сложно.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Ну и это тоже можно, и даже желательно, если разработчиков больше одного

Желательно? То есть, у тебя были проекты, где два разраба, которые не просматривают каждый коммит другого разраба?

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Всякое бывает, и причины могут быть разными.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Но тут всё очень просто - любой malloc должен быть обёрнут строкой вида

if(!(a = malloc(...))) return;

if(!(x = malloc(...))) {
  free(a);
}

...

a[42] = 69;
*b[13] = 0;

Вполне можно случайно пропустить при тестировании.

monk ★★★★★
()
Ответ на: комментарий от monk

Это уже из разряда опечаток, исправляется проверками кода при коммите. Вобщем-то, об этом выше другим пунктом ты уже писал.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Так более 90% ошибок являются опечатками и описками (думал одно, написал другое вида замены + на - или ошибка ±1). И единственный метод борьбы с этим — внимательность. То есть неустраним человеческий фактор.

monk ★★★★★
()
Ответ на: комментарий от firkax

Да. Но в языках с UB они могут приводить к порче данных. В безопасных же языках (лисп, джава, …) ошибка всегда локальна (портит только те данные, которые указаны в строке, где ошибка).

monk ★★★★★
()

Не такой он уж и мертвьій. Пентагон до сих пор юзает в своих встроенньіх системах, еще лет 40 юзать будет. Нет ему просто места в мейнстриме.

sbu_shpigun
()

Ада мертва бай дезигн. Её делали для вояк США, на крутое железо. Когда такое железо стало массовым, у ады не оказалось плюсов перед другими ЯП. Конечно, она удобнее фортрана, но сишка уже удобнее и ада проиграла конкуренцию.

peregrine ★★★★★
()
Ответ на: комментарий от monk

Нет. Те живы так как некоторые штуки нельзя сделать без ручного управления памятью/очень больно будет в плане производительности/потребления оперативки.

peregrine ★★★★★
()
Ответ на: комментарий от hateWin

Да для начала жесткую числодробилку, с активной работой с памятью, скажем какую-нибудь реализацию RandomForest-а или нейросетку. Там не то что сишку, фортран придётся расчехлять (если делать быстро и без готовых высокоуровневых библиотек). Хотя да, в теории можно без фортрана, но тогда чем LAPACK и BLAS менять не очень понятно. Придётся на сишке их реализовывать и тестировать очень долго и аккуратно. Кстати, у RandomForest-а будет явная проблема с фрагментацией памяти, потому как все эти маленькие ноды что там десятками тысяч создаются и удаляются в процессе обучения, неплохо так память раздувают. У нейронок, если там нейронный газ используется, тоже будут разные интересные эффекты, особенно если они графовые.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 2)
Ответ на: комментарий от Partisan

lisp применяют, но очень осторожно, там где он нужен в виде Clojure.

peregrine ★★★★★
()
Ответ на: комментарий от byko3y

Если за каждое падение твоей софтины тебе будут срезать половину ЗП, то ты первым побежишь учить жаву.

У меня сегодня софт на java падал. Что-то ему в версии jvm очень не нравилось и он задорно падал.

Так-то комфортно сидеть с позиции «мою софтину поломали? это просто тестеры плохо тестировали».

Для начала неплохо бы прикрутить статистическое тестирование кода, нанять тестеров и найти толкового безопасника (которых днём с огнём не сыщешь, потому что все они у вояк и там быстро портятся, т.к. по уставу думать не положено), который специализируется на поиске уязвимостей в софте.

peregrine ★★★★★
()
Ответ на: комментарий от hobbit

У вас наказывают программиста за то, что программа падает? Не хочу у вас работать.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Ада мертва бай дезигн. Её делали для вояк США, на крутое железо. Когда такое железо стало массовым, у ады не оказалось плюсов перед другими ЯП.

Какие-то противоречащие параграфы.

  1. Её делали для вояк США, на крутое железо. => на этом железе она была лучше других языков.

  2. Когда такое железо стало массовым, у ады не оказалось плюсов перед другими ЯП. => на этом железе она сейчас не лучше других языков.

???

monk ★★★★★
()
Ответ на: комментарий от peregrine

Те живы так как некоторые штуки нельзя сделать без ручного управления памятью/очень больно будет в плане производительности/потребления оперативки.

Так проверяли производительность. C++ без арены часто медленнее языков со сборщиком мусора. А с ареной ест больше системной памяти (так как арену очистить можно только целиком).

Вот бинарные деревья: 22,6 секунды C++ и 4,48 Java.

monk ★★★★★
()
Ответ на: комментарий от monk

При тестировании получить NULL от malloc достаточно тяжело

Вы что там, наугад программируете?

Чтобы получить гарантированно NULL от malloc в нужном месте, надо в дебаг-версии использовать модифицированный malloc, позволяющий получить NULL тогда, когда надо.

Psilocybe ★★★★★
()
Ответ на: комментарий от Psilocybe

надо в дебаг-версии использовать модифицированный malloc, позволяющий получить NULL тогда, когда надо

Ага. Почти всю стандартную модифицированную библиотеку от malloc до open. Которая при тестах выдаст все возможные ошибки.

И, если программа не должна после любой ошибки аварийно останавливаться, получаем комбинаторный взрыв всех обработчиков ошибок (что после обработки ошибки А от fopen при получении ошибки Б от mmap программа не портит данные).

monk ★★★★★
()
Ответ на: комментарий от Psilocybe

При чём тут программирование? Речь про то, что тестирование не спасает. Особенно, если ошибка проявляется нелокально.

Опять вернёмся к моему примеру. Сделали malloc, возвращающий NULL.

if(!(a = malloc(...))) return;

if(!(x = malloc(...))) {
  free(a);
}

При нём программа работает правильно, так как первая проверка произвела возврат, а до второй дело не дошло. Для того, чтобы ошибку воспроизвести, нужен malloc, который вернёт NULL на второй вызов и указатель на выделенную память на первый, третий и четвёртый. Причём воспроизведётся только продолжение выполнения, а не порча данных. Так как для порчи данных выделенная память должна строго определённым образом пересечься при первом и третьем вызове malloc.

monk ★★★★★
()
Ответ на: комментарий от monk

Там где-то должна быть секция очистки типа

void* a=null;
void* x=null;

...
if(!(a = malloc(...))) goto FREE;
if(!(x = malloc(...))) goto FREE;

......

:FREE
/* free(NULL) is guaranteed to be safe */
free(a);
free(x);

Если всё нормально структуировать, то проблем нет.

Psilocybe ★★★★★
()
Ответ на: комментарий от Psilocybe

void* a=null;

:-) Для кого программирование сложно?

Если всё нормально структуировать, то проблем нет.

В данном случае, да. Хотя мало кто так пишет, так как «страшный goto» считается вредным.

Ещё бывают конструкции типа:

a = malloc(N * sizeof(int));

...

for(i = 0; i <= N; i++) {
  ...
  if(f(i)) 
     a[i] = ...
} 

Тоже опечатка. И тоже при тестовом прогоне не всегда воспроизводится.

monk ★★★★★
()
Ответ на: комментарий от monk

ППКС. Поэтому программировать на С++ вы меня теперь калачом не заманите. Хватит с меня.

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от monk

Хотя мало кто так пишет, так как «страшный goto» считается вредным.

Тут Дейкстра и компания были не совсем правы. Управление потоком команд можно разделить на 2 типа: управление описывающее сам алгоритм и управление обработкой ошибок.

Goto «вредный» при программировании алгоритма, а вот для управления ошибками он в самый раз.

Тоже опечатка. И тоже при тестовом прогоне не всегда воспроизводится.

Почему свою мысль Вам приходится иллюстрировать лапшекодом и ковнокодом? То free между делом, то короткие имена, в которых легко ошибиться.

Psilocybe ★★★★★
()
Ответ на: комментарий от Psilocybe

Почему свою мысль Вам приходится иллюстрировать лапшекодом и ковнокодом? То free между делом, то короткие имена, в которых легко ошибиться.

Потому что так проще иллюстрировать ошибки. И в последнем примере ошибка не в коротком имени.

monk ★★★★★
()
Ответ на: комментарий от LongLiveUbuntu

Pascal - Modula - Modula-2 - Обероны. У Modula-2 были шансы стать хорошим системным ЯП.

Так Ден именно поэтому свой ЯОС на Обероне ваяет. Наследие он считает вредным, Аду переусложнённой (к тому же стандартная библиотека или за много денег или GPL).

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

на крутое железо. => на этом железе она была лучше других языков

FALSE

у ады не оказалось плюсов перед другими ЯП. => на этом железе она сейчас не лучше других языков

TRUE

peregrine ★★★★★
()
Ответ на: комментарий от monk

Тест написан криво. Нормальный код на c++ с использованием всех его возможностей, никак не может быть короче кода на Java

peregrine ★★★★★
()
Ответ на: комментарий от monk

Не уверен что на Java оно «честное». Таки надо уметь менеджить память. Можно положиться на то как умеет jvm, а можно ручками лучше сделать.

peregrine ★★★★★
()
Ответ на: комментарий от monk

Распилом и откатом, подконтрольностью компилятора. А ты думал что в США нет коррупции?

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

Не уверен что на Java оно «честное».

Оно честное в том смысле, что n.r = null удаляет узлы в правом поддереве сразу (при ближайшем запуске GC).

В Си++ быстрые варианты только те, где память под всё дерево находится в одной арене и, как следствие, память для части дерева освободить нельзя.

monk ★★★★★
()
Ответ на: комментарий от peregrine

Можно положиться на то как умеет jvm, а можно ручками лучше сделать.

Звучит как «Можно положиться на то как умеет GCC, а можно ручками на ассемблере лучше сделать».

korvin_ ★★★★★
()
Ответ на: комментарий от peregrine

Вот только он не на каждый чих вызывается

А зачем его на каждый чих вызывать? От скуки?

korvin_ ★★★★★
()
Ответ на: комментарий от peregrine

Вот только он не на каждый чих вызывается

Но достаточно часто. Для большинства сценариев использования допустимо освобождение памяти через миллисекунду после того, как она перестала быть доступна из программы. Но недопустимо не освобождать её до конца работы программы (как часто делается в моделях с ареной или со статическим захватом памяти «по максимуму» при запуске).

monk ★★★★★
()

Анабиоз не является смертью.

Mischutka ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.