R>Неужели тоже самое только (опять) вручную??? R>Или С-программисты делают как-то по-другому? В С-стиле программирования не силён, поэтому поправьте, если что.
Одна точка входа и одна точка выхода -> наиболее распространенный стиль программирования.
Примеры можно посмотреть в Linux или в Windows (DDK).
К>локальная переменная, скажем массив целых на 100000 байт, функция рекурсивная, как кончится память догадаешься?
К>Или у тебя своя терминология и локальная переменная только на стеке? но, надеюсь, ты в курсе, что стек вещь не бесконечная?
Смею вас уверить, что нехватка стека что в C++, что в C это смертельно, правда можно попытаться что-то сделать, но платформо зависимое.
P.S.
никто из знакомых мне программистов не выделит на стеке столько.
MShura wrote: > Нормальный подход. > Если в условиях задачи разрешено использовать структурные исключения, то > можно сделать через __try/__finally
Ну так это и есть ручная эмуляция исключений.
В данном случае С++ будет БЫСТРЕЕ, так как не надо проверять коды возврата.
MShura wrote:
>> > R> Разместить его на стеке? >> > Обычно это дополнительная (неуправляеммая вами) переменная, которая >> > используется для выяснения вызывался конструктор или нет. > _>Ты о чём? Зачем это выяснять? Вызов конструктора (если он есть!) > происходит в том месте, где поставлена переменная. Т.е. > А если возврат из функции произошел раньше вызова конструктора?
Он не вызовется. А ты что думал?
> Память для локальных переменных обычно выделяется при входе в функцию, > т.е. даже для того, объекта который будет проинициалирован позже память > уже выделена.
Как в С, так и в С++. И что?
> При раскрутке стека необходимо знать был ли проинициализорован объект с > нетривиальным деструктором.
Я привёл два листинга на С и С++ идентичные по коду.
А теперь мне покажи код на С, в котором будет нетривиальный деструктор (точнее его эмуляция) и кидание исключений
(точнее их эмуляция). Вот и будем их сравнивать, а пока фигню говоришь.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, MShura, Вы писали:
R>>Рассмотрим функцию на С:
MS>Одна точка входа и одна точка выхода -> наиболее распространенный стиль программирования. MS>Примеры можно посмотреть в Linux или в Windows (DDK).
>> Нормальный подход. >> Если в условиях задачи разрешено использовать структурные исключения, то >> можно сделать через __try/__finally C>Ну так это и есть ручная эмуляция исключений.
C>В данном случае С++ будет БЫСТРЕЕ, так как не надо проверять коды возврата.
Не вижу разницы если проект на C использует структурные исключения вместо кодов возврата.
C++ вызывает throw а в C RaiseException.
Если вы про new vs malloc, то элементарно сделать, чтобы malloc кидал структурное исключение.
Писанины больше, но и вся разница.
Кроме того, в структурных исключениях есть возможность продолжить выполнение с места исключения.
Очень удобно при формировании буферов неопределенной заранее длины.
Обычная задача оптимизации (как быстрее реализовать switch по таблице ссылок или прямым перебром — при небольшов варианте выбора прямой перебор быстрее).
Очень часто нет необходимости делать дополнительные проверки перед освобождением ресурсов.
Как показал сам Cyberax можно сделать несколько меток в конце функции (если ресурсы захватываются последовательно а именно так и происходит в большинстве функций), что убирает необходимость в дополнительных проверках.
Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle все равно проверяется перед вызовом CloseHandle.
(Хотя можно использовать full trusted обертку, но это редкость)
Если у Вас обертка над указателем, то написав delete компилятор вставляет код проверки на NULL, даже если вы как-то убедите его не делать этой проверки, то вызов функции OS для особождения памяти опять проверит указатель на NULL.
Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, что современные компиляторы умеют нивелировать косвенный вызов функции, что уж говорить об обычном ветвлении. К тому же есть подсказки компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу.
Одним словом я бы не стал категорично заявлять, что код освобождения ресурсов в C больше оного в C++.
, что то, что делает > С++ автоматически, тебе придётся делать > _>тоже самое вручную, к тому же только хуже, т.к. у тебя нет контроля > стека, какой есть у С++ компилятора. > _>С++ лишь увеличивает размер бинарника под таблицы раскрутки, а в С будет > > _>дополнительный исполняемый код, что замедлит в итоге. > <http://rsdn.ru/forum/?mid=2059458>
> > Обычная задача оптимизации (как быстрее реализовать switch по таблице > ссылок или прямым перебром — при небольшов варианте выбора прямой > перебор быстрее).
Хм?..
> Очень часто нет необходимости делать дополнительные проверки перед > освобождением ресурсов. > Как показал сам Cyberax можно сделать несколько меток в конце функции > (если ресурсы захватываются последовательно а именно так и происходит в
Если не используются исключения. В С++ их тоже можно отключить.
> большинстве функций), что убирает необходимость в дополнительных проверках.
Не делай доп проверки, что напишешь в деструкторе то и будет.
> Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle > все равно проверяется перед вызовом CloseHandle.
Да, и в чём отличие от С++?
> (Хотя можно использовать full trusted обертку, но это редкость) > Если у Вас обертка над указателем, то написав delete компилятор > вставляет код проверки на NULL, даже если вы как-то убедите его не > делать этой проверки, то вызов функции OS для особождения памяти опять > проверит указатель на NULL.
Причём тут функции ОС и С vs С++?
> Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, > что современные компиляторы умеют нивелировать *косвенный* вызов > функции, что уж говорить об обычном ветвлении. К тому же есть подсказки > компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу.
Да, заоптимайзить можно. Но причём тут С vs С++?
> Одним словом я бы не стал категорично заявлять, что код освобождения > ресурсов в C больше оного в C++.
В лучшем случае такой же, но никак не меньше. За счёт чего может быть меньше?
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Скорость работы с использованием классов и без
Здравствуйте, remark, Вы писали: R>Но большинство других функций не принимают размер.
Как правило, это те функции, которые не выиграют от знания размера. У них алгоритм устроен так, что последовательное сканирование их вполне устраивает.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
MShura wrote: > C>Ну так это и есть ручная эмуляция исключений. > C>В данном случае С++ будет БЫСТРЕЕ, так как не надо проверять коды > возврата. > Не вижу разницы если проект на C использует структурные исключения > вместо кодов возврата.
Для SEH нужно делать настройки каждого фрейма функции. Для исключений
С++ — необязательно.
> C++ вызывает throw а в C RaiseException. > Если вы про new vs malloc, то элементарно сделать, чтобы malloc кидал > структурное исключение. > Писанины больше, но и вся разница. > Кроме того, в структурных исключениях есть возможность продолжить > выполнение с места исключения.
1. Где у нас SEH на Линуксе?
2. Как сделать SEH с zero-overhead по скорости?
MShura wrote: > Как показал сам Cyberax можно сделать несколько меток в конце функции > (если ресурсы захватываются последовательно а именно так и происходит в > большинстве функций), что убирает необходимость в дополнительных проверках. > Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle > все равно проверяется перед вызовом CloseHandle.
Я вообще-то просил сказать чем это отличается от семантики
автоматических деструкторов (ответ: почти ничем).
> Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, > что современные компиляторы умеют нивелировать *косвенный* вызов > функции, что уж говорить об обычном ветвлении. К тому же есть подсказки > компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу.
Ну тогда какие вопросы к С++, который просто при инициализации объекта
устанавливает флаг?
> Одним словом я бы не стал категорично заявлять, что код освобождения > ресурсов в C больше оного в C++.
Больше. В С++ с умными указателями тот же код:
>> >> Обычная задача оптимизации (как быстрее реализовать switch по таблице >> ссылок или прямым перебром — при небольшов варианте выбора прямой >> перебор быстрее). _>Хм?..
Это я к тому, что можно реализовать такой вариет освобождения ресурсов.
Иногда в больших функция имеет смысл.
void Func()
{
int res = -1;
char* a, *b;
a = (char*)malloc( 100 );
if ( NULL == a )
goto Exit;
res = 0;
b = (char*)malloc( 100 );
if ( NULL == b )
goto Exit;
res = 1;
err = Func2( a, b );
Exit:
switch( res )
{
case 1: free( b );
case 0: free( a );
}
}
>> Очень часто нет необходимости делать дополнительные проверки перед >> освобождением ресурсов. >> Как показал сам Cyberax можно сделать несколько меток в конце функции >> (если ресурсы захватываются последовательно а именно так и происходит в _>Если не используются исключения. В С++ их тоже можно отключить.
Если отлючить исключения C++, тогда производительность C++ будет приближаться к производительности C.
Только в этом случае.
>> большинстве функций), что убирает необходимость в дополнительных проверках. _>Не делай доп проверки, что напишешь в деструкторе то и будет.
>> Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle >> все равно проверяется перед вызовом CloseHandle. _>Да, и в чём отличие от С++?
>> (Хотя можно использовать full trusted обертку, но это редкость) >> Если у Вас обертка над указателем, то написав delete компилятор >> вставляет код проверки на NULL, даже если вы как-то убедите его не >> делать этой проверки, то вызов функции OS для особождения памяти опять >> проверит указатель на NULL. _>Причём тут функции ОС и С vs С++?
Вышесказанное было приведено к тому, что помимо "явных" проверок перед освобождением ресурсов будут многочисленные и даже недешевые дополнительные проверки.
>> Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, >> что современные компиляторы умеют нивелировать *косвенный* вызов >> функции, что уж говорить об обычном ветвлении. К тому же есть подсказки >> компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу. _>Да, заоптимайзить можно. Но причём тут С vs С++?
Это к вариантам освобождения switch() vs "одна переменная для каждого ресурса"
>> Одним словом я бы не стал категорично заявлять, что код освобождения >> ресурсов в C больше оного в C++. _>В лучшем случае такой же, но никак не меньше. За счёт чего может быть меньше?
Имелось в в виду не написанный, а сгенеренный код.
>> Как показал сам Cyberax можно сделать несколько меток в конце функции >> (если ресурсы захватываются последовательно а именно так и происходит в >> большинстве функций), что убирает необходимость в дополнительных проверках. >> Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle >> все равно проверяется перед вызовом CloseHandle. C>Я вообще-то просил сказать чем это отличается от семантики C>автоматических деструкторов (ответ: почти ничем).
>> Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, >> что современные компиляторы умеют нивелировать *косвенный* вызов >> функции, что уж говорить об обычном ветвлении. К тому же есть подсказки >> компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу. C>Ну тогда какие вопросы к С++, который просто при инициализации объекта C>устанавливает флаг?
Отвечаю на два вопроса.
В C можно никаких дополнительных переменных (неявных) не заводить.
>> Одним словом я бы не стал категорично заявлять, что код освобождения >> ресурсов в C больше оного в C++. C>Больше. В С++ с умными указателями тот же код: C>
C>Все! Причем нельзя забыть поставить cleanup в конце.
Конечно код написанный программистом на C++ будет меньше в текстовом виде, но больше в двоичном.
пример:
#include <memory>
using namespace std;
void FuncCpp( auto_ptr<char>& a, auto_ptr<char>& b );
void TestCpp()
{
auto_ptr<char> a ( new char [100] );
auto_ptr<char> b ( new char [100] );
FuncCpp( a, b );
}
#include <errno.h>
unsigned FuncC( char* a, char* b );
int TestC()
{
int err = -ENOMEM;
char* a, *b;
a = (char*)malloc( 100 );
if ( NULL == a )
goto end1;
b = (char*)malloc( 100 );
if ( NULL == b )
goto end2;
err = FuncC( a, b );
free( b );
end2:
free( a );
end1:
return err;
}
Т.е. кода обработки ошибок НЕТ вообще! Т.е. С++ код в отсутсвие исключений даже ПРОЩЕ, чем С код. Есть пролог и эпилог
функции, которые не содежрат условных операторов и переходов (хотя за счёт увеличения стека). И asm данной функции на
С++ получился вообще без условных переходов, в отличие от С. Дополнительный код будет выполнятся только при
возникновении исключений (а по замыслу это редкие ситуации в С++).
cl /O2 /FAs /EHs
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай