Re[3]: Разработка на чистом C
От: kov_serg Россия  
Дата: 31.10.16 05:00
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, kov_serg, Вы писали:


_>>На чистом С несколько иной подход. Тут более важна организация кода, а не конкретные локальные приёмы.


EP>RAII и исключения это глобальные приёмы. Про "иной подход" на C можно вот тут почитать.

Именно приёмы. И эти приёмы не решают реальные задачи. Скажу страшную вещь исключения "нинужны"
Автор: push
Дата: 06.09.16


_>>Совершенно не обязательно тащить универсальность из C++ иногда есть требования запрещающие использование динамической памяти и вполне себе компилируется и работает на ограниченных ресурсах с заранее выделенными массивами для обработки.


EP>C++ прекрасно работает в таких рамках.

Особенно если под целевую платформу нет компилятора C++? Отсутствие всех удобств C++ по началу связывает руки, но потом выясняется что без всего этого можно спокойно обойтись. Даже возможность объявлять переменную где угодно скорее засоряет код чем облегчаетнаписание, особенно если это название шаблона с параметрами глубоко заныкаными в наймспейсах.
Re[4]: Разработка на чистом C
От: Evgeny.Panasyuk Россия  
Дата: 31.10.16 05:41
Оценка: +1
Здравствуйте, kov_serg, Вы писали:

_>>>На чистом С несколько иной подход. Тут более важна организация кода, а не конкретные локальные приёмы.

EP>>RAII и исключения это глобальные приёмы. Про "иной подход" на C можно вот тут почитать.
_>Именно приёмы.

Приёмы влияющие на код глобально

_>И эти приёмы не решают реальные задачи.


Смотри страдания по приведённой ссылке

_>>>Совершенно не обязательно тащить универсальность из C++ иногда есть требования запрещающие использование динамической памяти и вполне себе компилируется и работает на ограниченных ресурсах с заранее выделенными массивами для обработки.

EP>>C++ прекрасно работает в таких рамках.
_>Особенно если под целевую платформу нет компилятора C++?

Отсутствие компилятора это один из немногих случаев где оправданно использование C, по очевидным причинам.

_>Отсутствие всех удобств C++ по началу связывает руки, но потом выясняется что без всего этого можно спокойно обойтись.


Обойтись-то естественно можно, но более дорогой ценной.
Re[3]: Разработка на чистом C
От: smeeld  
Дата: 31.10.16 05:53
Оценка:
Здравствуйте, uncommon, Вы писали:


U>Лёня Поттер с тобой не согласен. Он предпочитает GCC cleanup attribute, а это почти что RAII.


Они там клепать могут что угодно, это опенсорс, это делается just for fun. Вот тольно Линус следит, чтоб все эти новомодные фишки линуксовое ядро никак не затрагивали и материт если затрагивают, ибо они все толко проблемы создают и вредят. Простой пример когда эта RAII превращается в банальный ненужный гемор привёл выше.
Re: Разработка на чистом C
От: pestis  
Дата: 31.10.16 06:11
Оценка: 12 (1)
Здравствуйте, Lonely Dog, Вы писали:

LD>Может есть какие-нибудь книги? Думаю, посмотреть что-то типа Writing device drivers for Linux.


Functional Programming in C, Design Patterns in pure C, Modern C programming.
Re[7]: Разработка на чистом C
От: pestis  
Дата: 31.10.16 06:14
Оценка:
Здравствуйте, b0r3d0m, Вы писали:

B>Я пишу код вместе с людьми, а людям, как известно, свойственно ошибаться. Вы хотите сказать, что ни разу не встречали ни одной ошибки, связанной с пропущенной деинициализацией?


Существуют простые и очевидные меры по организации кода и рабочего процесса, позволяющие не допускать ошибок, связанных с утечками ресурсов. Если кто-то не использует эти меры, он ССЗБ.
Re[7]: Разработка на чистом C
От: pestis  
Дата: 31.10.16 06:17
Оценка:
Здравствуйте, b0r3d0m, Вы писали:

B>И что за организация владения ресурсами такая?


Например, выделять и освобождать ресурсы внутри одной функции.
Re[3]: Разработка на чистом C
От: Pavel Dvorkin Россия  
Дата: 31.10.16 06:46
Оценка: 1 (1)
Здравствуйте, push, Вы писали:

P>Здравствуйте, smeeld, Вы писали:


S>>Обработка исключений в С++ слишком дорогая операция,

P>По сравнению с чем? По сравнению с полным отказом от обработки ошибок — то да, дорогая. А если сравнивать с ручной обработкой ошибок — так можно сказать ничего не стоит.

int ErrorCodeFunction()
{
    return 1;
}

void ThrowFunction() {
    throw 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwTimeStart, dwTimeEnd;

    int count = 1000000;

    dwTimeStart = GetTickCount();
    for (int i = 0; i < count; i++)
    {
        int result = ErrorCodeFunction();
    }
    dwTimeEnd = GetTickCount();

    printf("Error code time = %d\n", dwTimeEnd - dwTimeStart);

    dwTimeStart = GetTickCount();
    for (int i = 0; i < count; i++)
    {
        try {
            ThrowFunction();
        }
        catch(...) {}
    }
    dwTimeEnd = GetTickCount();

    printf("Try catch time = %d\n", dwTimeEnd - dwTimeStart);

    return 0;
}



Error code time = 15
Try catch time = 9000

Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.

Так что не надо заявлять, что обработка исключений столь уже дешева. Это все же вызов ядра (throw в VC++ вызывает RaiseException)
With best regards
Pavel Dvorkin
Отредактировано 31.10.2016 6:51 Pavel Dvorkin . Предыдущая версия . Еще …
Отредактировано 31.10.2016 6:50 Pavel Dvorkin . Предыдущая версия .
Re[8]: Разработка на чистом C
От: okman Беларусь https://searchinform.ru/
Дата: 31.10.16 07:28
Оценка: +1
Здравствуйте, pestis, Вы писали:

P>Существуют простые и очевидные меры по организации кода и рабочего процесса, позволяющие не допускать ошибок, связанных с утечками ресурсов.


Можно вот с этого места поподробнее?

Сейчас как раз занимаюсь рефакторингом старого кода на C.

Есть объекты (структуры), которые хранят информацию, связанную с операциями ввода-вывода
на соответствующих объектах системы — файлы, папки, устройства и т.д. Объекты массово
создаются, живут, изменяются и уничтожаются, все это параллельно, в разных потоках.
Время жизни управляется подсчетом ссылок.

Проблема: работа с этими объектами "размазана" по всему коду, всего около трехсот
таких мест, некоторые фрагменты кода достаточно длинные и запутанные.

Вопрос: как обеспечить гарантию того, что тот, кто после меня будет работать с
этим кодом, не забудет вставить release_object в нужное место и освободить ссылку?
На C++ я бы взял shared_ptr и большая часть проблемы была бы решена автоматически.

Вот и говорите после этого, что RAII не нужен.
Re[9]: Разработка на чистом C
От: pestis  
Дата: 31.10.16 07:50
Оценка: :))) :)
Здравствуйте, okman, Вы писали:


O>Сейчас как раз занимаюсь рефакторингом старого кода на C.


Зачем вам это понадобилось? Почему код именно на C? Какие у вас есть возможности, полномочия, ресурсы?

O>Есть объекты (структуры), которые хранят информацию, связанную с операциями ввода-вывода

O>на соответствующих объектах системы — файлы, папки, устройства и т.д. Объекты массово
O>создаются, живут, изменяются и уничтожаются, все это параллельно, в разных потоках.
O>Время жизни управляется подсчетом ссылок.

Не нужно создавать и удалять ресурсы в разных потоках. Вообще нежелательно использовать несколько потоков в С. Для этого есть более подходящие языки, которые, при необходимости прекрасно интегрируются с C кодом.

O>Проблема: работа с этими объектами "размазана" по всему коду, всего около трехсот

O>таких мест, некоторые фрагменты кода достаточно длинные и запутанные.

Общее правило, места где выделяются ресурсы и места где освобождаются ресурсы должны быть локализованы и размечены комментариями. Код, использующий ресурсы может быть сколь угодно сложные, но он не должен ни выделять, ни освобождать ресурсы. Т.е. выделили ресурсы, посчитали, освободили ресурсы.

O>Вопрос: как обеспечить гарантию того, что тот, кто после меня будет работать с

O>этим кодом, не забудет вставить release_object в нужное место и освободить ссылку?

Выделение и освобождение ресурсов должно быть рядом и размечено комментариями "тут выделил, там освободи". Любой код выделяющий ресурс, должен проходить peer review на предмет освобождения ресурса.

O>На C++ я бы взял shared_ptr и большая часть проблемы была бы решена автоматически.


На Python у вас была бы автоматическая сборка мусора и try/catch/finally блоки. А на Clojure у вас был бы software transactional memory.
Re[9]: Разработка на чистом C
От: lpd Черногория  
Дата: 31.10.16 07:54
Оценка: :)
Здравствуйте, okman, Вы писали:

O>Здравствуйте, pestis, Вы писали:


P>>Существуют простые и очевидные меры по организации кода и рабочего процесса, позволяющие не допускать ошибок, связанных с утечками ресурсов.


O>Можно вот с этого места поподробнее?


O>Сейчас как раз занимаюсь рефакторингом старого кода на C.


O>Есть объекты (структуры), которые хранят информацию, связанную с операциями ввода-вывода

O>на соответствующих объектах системы — файлы, папки, устройства и т.д. Объекты массово
O>создаются, живут, изменяются и уничтожаются, все это параллельно, в разных потоках.
O>Время жизни управляется подсчетом ссылок.

O>Проблема: работа с этими объектами "размазана" по всему коду, всего около трехсот

O>таких мест, некоторые фрагменты кода достаточно длинные и запутанные.

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

O>Вопрос: как обеспечить гарантию того, что тот, кто после меня будет работать с

O>этим кодом, не забудет вставить release_object в нужное место и освободить ссылку?
O>На C++ я бы взял shared_ptr и большая часть проблемы была бы решена автоматически.

shared_ptr неудобен и все равно нужно в некоторых местах использовать weak_ptr из-за кольцевых ссылок, что только усложняет дело.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[3]: Разработка на чистом C
От: T4r4sB Россия  
Дата: 31.10.16 07:54
Оценка: +3
Здравствуйте, uncommon, Вы писали:

U>Здравствуйте, smeeld, Вы писали:


S>>RAII тоже сомнительная фича.


U>Лёня Поттер с тобой не согласен. Он предпочитает GCC cleanup attribute, а это почти что RAII.


U>И вообще в GCC вагон и маленькая тележка всяких расширений, без которых жизнь в C не мила.


Вот это мегакостыль, оставаться на сишке ради того, чтобы расширениями переизобрести в ней С++, долбанулись что ли.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[9]: Разработка на чистом C
От: VTT http://vtt.to
Дата: 31.10.16 07:55
Оценка: :))) :)
Здравствуйте, okman, Вы писали:

O>Здравствуйте, pestis, Вы писали:


P>>Существуют простые и очевидные меры по организации кода и рабочего процесса, позволяющие не допускать ошибок, связанных с утечками ресурсов.


O>Можно вот с этого места поподробнее?


Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[4]: Разработка на чистом C
От: _NN_  
Дата: 31.10.16 09:41
Оценка: 20 (2) +1 -2
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.


PD>Так что не надо заявлять, что обработка исключений столь уже дешева. Это все же вызов ядра (throw в VC++ вызывает RaiseException)

Давай правильно сравнивать.
Кинуть исключение дороже чем вернуть значение, с этим никто не спорит.
Однако, исключения это исключительная ситуация, а посему это должно быть редким явлением.

А теперь сравним именно такой код:

#include <windows.h>

int ErrorCodeFunction(int count)
{
    if (count < -1) return 0;
    return count > 100 ? 1 : 2;
}

int ThrowFunction(int count) {
    if (count < -1) throw 1;
    return count > 100 ? 1 : 2;
}

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwTimeStart, dwTimeEnd;

    int count = 1000000;

    dwTimeStart = GetTickCount();
    for (int i = 0; i < count; i++)
    {
        int result = ErrorCodeFunction(count);
    }
    dwTimeEnd = GetTickCount();

    printf("Error code time = %d\n", dwTimeEnd - dwTimeStart);

    dwTimeStart = GetTickCount();
    for (int i = 0; i < count; i++)
    {
        try {
            int result = ThrowFunction(count);
        }
        catch (...) {}
    }
    dwTimeEnd = GetTickCount();

    printf("Try catch time = %d\n", dwTimeEnd - dwTimeStart);

    return 0;
}


Release:
Error code time = 0
Try catch time = 0


Увеличим количество итераций: int count = 100*1000*1000;
Release:
Error code time = 47
Try catch time = 62

Получаем разницу 15ms/10*1000*1000 = 1.5ns.
Не так много учитывая упрощение кода.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Разработка на чистом C
От: Pzz Россия https://github.com/alexpevzner
Дата: 31.10.16 10:06
Оценка: 4 (1) +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Pzz>>Ну да, так и пишем, все руками. Полезность C++'ных автоматизмов сильно переоценена. В том смысле, что необходимость делать все явно добавляет, конечно, работы, но не так, чтобы очень много.


EP>Error-prone, легко забыть и трудно поддерживать.


Все эти C++'ные автоматизмы тоже error-prone. Особенно если учесть, как хорошо и неочевидно они могут быть запрятаны.

Pzz>>Обработка ошибок в виде явно возвращаемых кодов возврата — это не такой уж и плохой вариант. В отличии от исключений, все перед глазами и все легко читается, ошибка не прилетит неизвестно откуда и не улетит неизвестно куда.


EP>Error codes точно также летят наверх неизвестно куда.

EP>Хотя часто вообще не летят, ибо на них забивают — пример
Автор: MTD
Дата: 21.02.13
.


Там явно последовательность вызовов, которые вряд ли могут вернуть ошибку. Поэтому ребята притомились и перестали проверять

Для такого случая, как в том примере, есть еще один неплохой вариант. Пусть этот sAIMenu запоминает внутри себя, что очередное издевательство над ним вернуло ошибку, и игнорирует все последущие. Тогда можно смело совершенно написать 100500 действий в столбик, и проверить, нет ли там запомненной ошибки, в самом конце.

А еще можно, чем добавлять item'ы в меню сотней последовательных вызовов, сделать из них табличку и пройтись по ним циклом. Тогда ошибку придется проверять в одном месте внутри цикла, а не при каждом вызове, код станет короче, проще и более поддерживаемый.

В общем, все можно сделать аккуратно независимо от языка.

Pzz>>setjmp/longjmp для обработки ошибок очень мало подходят, это экзотические функции, которые бывают полезны в редких случаях.


EP>Их используют для эмуляции исключений.


И это не самый хороший подход.
Re[4]: Разработка на чистом C
От: landerhigh Пират  
Дата: 31.10.16 10:22
Оценка: +1
Здравствуйте, smeeld, Вы писали:

S>Вот у Вас объект, он должен содержать установленное соединение с удалённым хостом, у нас RAII, поэтому соединение должно устанавливаться в конструкторе (типа никаких init/create). Более того, мы, как крутые C++-ники, обязательно сделаем emplace этого объекта в какой-нибудь контейнер, так как экземпляров этих объектов в программе создаётся много и чтоб руками их не уничтожать, нужно чтоб они уничтожались автоматически, которые не были унитожены в процессе исполнения. Так же мы не должны откатываться куда-то далеко, так как ошибка в установлении одного соединения, не значит, что будет ошибка в установлении другого соединения, при создании другого экземпляра. Что это значит?


Это значит, что проектировать нужно правильно. А не бросаться с шашкой наголо на танк. Устанавливать соединение в конструкторе? Ну можно, наверное.
Хинт — установление соединения всегда длительная и обычно весьма асинхронная операция.

S>А то, что при использовании каждого экземпляра, нам нужно будет постоянно проверять, установилось ли там соединение в конструкторе при создании экземпляра, или нет.


Второй хинт — при использовании любого "соединения" всегда нужно быть готовым к тому, что соединение, которое еще такт назад было "хорошим", вдруг стало "плохим". Более того, нужно быть готовым к тому, что соединение испортилось в процессе использования.
И тут внезапно удобство исключений становится как бы весьма очевидным.
Re[5]: Разработка на чистом C
От: Carc Россия http://www.amlpages.com/home.php
Дата: 31.10.16 10:25
Оценка:
_NN>Получаем разницу 15ms/10*1000*1000 = 1.5ns.
_NN>Не так много учитывая упрощение кода.
Ну наконец-то, хоть кто-то вменяемый.

Исключения нужно юзать осторожно, и к их понимаю когда и почему и для чего их следует юзать, приходишь ой как не скоро. Это уже про архитектуру системы, а к таким пониманиям долго идти. А вы тут школота, школота, RAII они в конструктор пихнутЪ — об чем вы?
Школоте дали веревку достаточной длины, вот они и палят во все стороны. А "веревка" тут кстати не виновата.

В исключениях ключевое слово к примеру "библиотека". Кто в теме, тот меня понял
Aml Pages Home
Отредактировано 31.10.2016 10:26 Carc . Предыдущая версия .
Re[6]: Разработка на чистом C
От: _NN_  
Дата: 31.10.16 10:36
Оценка: 1 (1)
Здравствуйте, Carc, Вы писали:


_NN>>Получаем разницу 15ms/10*1000*1000 = 1.5ns.

_NN>>Не так много учитывая упрощение кода.
C>Ну наконец-то, хоть кто-то вменяемый.

C>Исключения нужно юзать осторожно, и к их понимаю когда и почему и для чего их следует юзать, приходишь ой как не скоро. Это уже про архитектуру системы, а к таким пониманиям долго идти. А вы тут школота, школота, RAII они в конструктор пихнутЪ — об чем вы :??? :? Школоте дали веревку достаточной длины, вот они и палят во все стороны. А "веревка" тут кстати не виновата.

Поэтому как раз исключение в конструкторе то что нужно.
1. Исключение бросается только в случае исключительной ситуации когда создать объект не имеет смысла.
Пример:
class A 
{
 A(int count)
 {
  // Меньше 10 в коде не будет, а если кто-то опечатался пускай получает.
  if(count<10) throw exception("ERROR");
 }
}

2. Если это не исключительная ситуация, а часть работы программы, то не должно быть исключения.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Разработка на чистом C
От: lpd Черногория  
Дата: 31.10.16 10:48
Оценка: 8 (1)
Здравствуйте, _NN_, Вы писали:

_NN>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.


PD>>Так что не надо заявлять, что обработка исключений столь уже дешева. Это все же вызов ядра (throw в VC++ вызывает RaiseException)

_NN>Давай правильно сравнивать.
_NN>Кинуть исключение дороже чем вернуть значение, с этим никто не спорит.
_NN>Однако, исключения это исключительная ситуация, а посему это должно быть редким явлением.

_NN>А теперь сравним именно такой код:


_NN> ...

_NN>Получаем разницу 15ms/10*1000*1000 = 1.5ns.
_NN>Не так много учитывая упрощение кода.

Пример абсолютно бессмысленный т.к. count всегда >0.

Чистый C применяется только в ядре,где нужно работать с оборудованием и C++ только мешает, и в коде embedded устройств. Последние нередко real-time и задержки на обработку исключений составляют существенную проблему и недопустимы.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[7]: Разработка на чистом C
От: Carc Россия http://www.amlpages.com/home.php
Дата: 31.10.16 11:00
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>2. Если это не исключительная ситуация, а часть работы программы, то не должно быть исключения.

Именно это я и имел ввиду! Что ситуация должна быть исключительной!!!

А этому просто не учили. Так, между делом, брякнут на лекции "исключения для исключительных ситуаций", ну понятно. А что такое исключительная ситуация никто и не объяснит, ибо сами не знают.

И вообще немного я видел литературы про как "готовить исключения". Именно как "готовить", а не в стиле "тут посолить командой throw", а тут "подать на стол" командой catch. Для этого у нас есть официантки, ой простите, "разрабы, которые не как поциенты клиники для склеротиков" (©).
А именно когда и почему и как пользоваться исключениями. У Бека было неплохо, а Мейерса есть неплохие мысли. Да и пожалуй, что все.

Я таки долго доходил своими мозгами когда "оно надо", пока не написал мутно-ядреный полубиблиотечный код с кучей маткриптографии внутри и в нагрузку кучи "дряни" аля "хак" (ибо этот код для защиты использовался).
Вот я пошел по пути кодов возврата, как тут разрабы_которые_не_такие, которые не ошибаются. Ох и наелся я ребята всякого. А главное юзера мои откушали полной ложкой, славу богу всего парочка, и огромное им спасибо за помощь и репорты.

Были б исключения сделал, проблем бы и не было в вовсе. А так…
Для сишников: не важно насколько красивый\быстрый\недорогой_в_ресурсах ваш код, если ваш код не работает.

PS: Для законченных сишников: "код не работает" это не означает Access Vioalation или просто тормоза. Это значит — вы не поверите — что он не делает того, что от не требуется, или делает, но не так, как ожидают от него.
Aml Pages Home
Отредактировано 31.10.2016 11:10 Carc . Предыдущая версия .
Re[6]: Разработка на чистом C
От: Carc Россия http://www.amlpages.com/home.php
Дата: 31.10.16 11:09
Оценка:
lpd>Чистый C применяется только в ядре,где нужно работать с оборудованием и C++ только мешает, и в коде embedded устройств. Последние нередко real-time и задержки на обработку исключений составляют существенную проблему и недопустимы.
С этим я абсолютно согласен. Я просто против оголотелого "ДваПлюса плохи\прекрасны\тормозы" или "Чистый Си прекрасен\плох\гемороен" (нужное подчеркнуть).

Кинжал хорош для того, у кого он окажется в нужный момент, и плох для того, у кого не окажется (С) Белое Солнце пустыни


Все очень сильно зависит от задачи. А оголтелая критика, как и восхваление, это по моему признак небольшого опыта. "Мудрым способно сомневаться" (тоже (ц)).
Aml Pages Home
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.