Re[15]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 15:18
Оценка:
R>Рассмотрим функцию на С:

R>
R>void some_func()
R>{
R>  some_struct s;
R>  bool s_init = false;

R>  //...

R>  if (a)
R>  {
R>    //...
R>    init_some_struct(&s);
R>    s_init = true;
R>    //...
R>  }

R>  //...

R>  if (b)
R>  {
R>    //...
R>    if (s_init)
R>       uninit_some_struct(&s);
R>    return;
R>  }

R>  //...

R>  if (s_init)
R>     uninit_some_struct(&s);
R>}
R>



R>Неужели тоже самое только (опять) вручную???

R>Или С-программисты делают как-то по-другому? В С-стиле программирования не силён, поэтому поправьте, если что.

Одна точка входа и одна точка выхода -> наиболее распространенный стиль программирования.
Примеры можно посмотреть в Linux или в Windows (DDK).
Re[15]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 15:22
Оценка:
К>локальная переменная, скажем массив целых на 100000 байт, функция рекурсивная, как кончится память догадаешься?

К>Или у тебя своя терминология и локальная переменная только на стеке? но, надеюсь, ты в курсе, что стек вещь не бесконечная?


Смею вас уверить, что нехватка стека что в C++, что в C это смертельно, правда можно попытаться что-то сделать, но платформо зависимое.

P.S.
никто из знакомых мне программистов не выделит на стеке столько.
Re[14]: Переформулируем вопрос
От: Cyberax Марс  
Дата: 15.08.06 15:27
Оценка:
MShura wrote:
> Нормальный подход.
> Если в условиях задачи разрешено использовать структурные исключения, то
> можно сделать через __try/__finally
Ну так это и есть ручная эмуляция исключений.

В данном случае С++ будет БЫСТРЕЕ, так как не надо проверять коды возврата.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[8]: Переформулируем вопрос
От: kan_izh Великобритания  
Дата: 15.08.06 15:28
Оценка:
MShura wrote:

>> > R> Разместить его на стеке?

>> > Обычно это дополнительная (неуправляеммая вами) переменная, которая
>> > используется для выяснения вызывался конструктор или нет.
> _>Ты о чём? Зачем это выяснять? Вызов конструктора (если он есть!)
> происходит в том месте, где поставлена переменная. Т.е.
> А если возврат из функции произошел раньше вызова конструктора?
Он не вызовется. А ты что думал?

> Память для локальных переменных обычно выделяется при входе в функцию,

> т.е. даже для того, объекта который будет проинициалирован позже память
> уже выделена.
Как в С, так и в С++. И что?

> При раскрутке стека необходимо знать был ли проинициализорован объект с

> нетривиальным деструктором.
Я привёл два листинга на С и С++ идентичные по коду.
А теперь мне покажи код на С, в котором будет нетривиальный деструктор (точнее его эмуляция) и кидание исключений
(точнее их эмуляция). Вот и будем их сравнивать, а пока фигню говоришь.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[16]: Переформулируем вопрос
От: remark Россия http://www.1024cores.net/
Дата: 15.08.06 15:29
Оценка:
Здравствуйте, MShura, Вы писали:

R>>Рассмотрим функцию на С:


MS>Одна точка входа и одна точка выхода -> наиболее распространенный стиль программирования.

MS>Примеры можно посмотреть в Linux или в Windows (DDK).

Ты лучше скажи по поводу s_init


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[15]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 15:38
Оценка: 1 (1)
>> Нормальный подход.
>> Если в условиях задачи разрешено использовать структурные исключения, то
>> можно сделать через __try/__finally
C>Ну так это и есть ручная эмуляция исключений.

C>В данном случае С++ будет БЫСТРЕЕ, так как не надо проверять коды возврата.

Не вижу разницы если проект на C использует структурные исключения вместо кодов возврата.
C++ вызывает throw а в C RaiseException.
Если вы про new vs malloc, то элементарно сделать, чтобы malloc кидал структурное исключение.
Писанины больше, но и вся разница.
Кроме того, в структурных исключениях есть возможность продолжить выполнение с места исключения.
Очень удобно при формировании буферов неопределенной заранее длины.
Re[17]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 15:40
Оценка:
R>Ты лучше скажи по поводу s_init

Одна точка входа -> одна точка выхода:

void some_func()
{
  some_struct s;
  bool s_init = false;

  //...

  if (a)
  {
    //...
    init_some_struct(&s);
    s_init = true;
    //...
  }

  //...

  if (b)
  {
    //...
    goto Exit;
//    if (s_init)
//       uninit_some_struct(&s);
//    return;
  }

  //...

Exit:
  if (s_init)
     uninit_some_struct(&s);
}
Re[9]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 15:43
Оценка:
Уважаемый Cyberax понял о чем речь.

http://www.rsdn.ru/Forum/Message.aspx?mid=2059458&only=1
Автор: Cyberax
Дата: 15.08.06
Re[10]: Переформулируем вопрос
От: kan_izh Великобритания  
Дата: 15.08.06 15:59
Оценка:
MShura wrote:

> Уважаемый Cyberax понял о чем речь.

Он объяснил
Автор: Cyberax
Дата: 15.08.06
, что то, что делает С++ автоматически, тебе придётся делать
тоже самое вручную, к тому же только хуже, т.к. у тебя нет контроля стека, какой есть у С++ компилятора.
С++ лишь увеличивает размер бинарника под таблицы раскрутки, а в С будет <br />
дополнительный исполняемый код, что замедлит в итоге.
Автор: Cyberax
Дата: 15.08.06
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[11]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 16:45
Оценка:
>> Уважаемый Cyberax понял о чем речь.
_>Он объяснил
Автор: Cyberax
Дата: 15.08.06
, что то, что делает С++ автоматически, тебе придётся делать

_>тоже самое вручную, к тому же только хуже, т.к. у тебя нет контроля стека, какой есть у С++ компилятора.
_>С++ лишь увеличивает размер бинарника под таблицы раскрутки, а в С будет <br />
<span class='lineQuote level1'>_&gt;дополнительный исполняемый код, что замедлит в итоге.</span>
Автор: Cyberax
Дата: 15.08.06


Обычная задача оптимизации (как быстрее реализовать switch по таблице ссылок или прямым перебром — при небольшов варианте выбора прямой перебор быстрее).

Очень часто нет необходимости делать дополнительные проверки перед освобождением ресурсов.
Как показал сам Cyberax можно сделать несколько меток в конце функции (если ресурсы захватываются последовательно а именно так и происходит в большинстве функций), что убирает необходимость в дополнительных проверках.
Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle все равно проверяется перед вызовом CloseHandle.
(Хотя можно использовать full trusted обертку, но это редкость)
Если у Вас обертка над указателем, то написав delete компилятор вставляет код проверки на NULL, даже если вы как-то убедите его не делать этой проверки, то вызов функции OS для особождения памяти опять проверит указатель на NULL.

Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, что современные компиляторы умеют нивелировать косвенный вызов функции, что уж говорить об обычном ветвлении. К тому же есть подсказки компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу.

Одним словом я бы не стал категорично заявлять, что код освобождения ресурсов в C больше оного в C++.

На этом заканчиваю на сегодня.
Re[12]: Переформулируем вопрос
От: MShura  
Дата: 15.08.06 16:47
Оценка:
MS>Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал, что современные компиляторы ...
Речь конечно о процессорах.
Re: Скорость работы с использованием классов и без
От: pavel_turbin  
Дата: 15.08.06 16:54
Оценка:
притормаживает большее количество временных объектов.

В C++ часто пишут


struct A
{
   string data;
};

vector<A> my_vector;

a1 = { "test" };
a2 = { "some other " };

my_vector.push_back( a1 ); 
my_vector.push_back( a2 );


при таком подходе возниканет несколько временных объектов и их копирование. Это замедляет. Особенно, если размер объекта большой или их много.
Re[12]: Переформулируем вопрос
От: kan_izh Великобритания  
Дата: 15.08.06 17:04
Оценка:
MShura wrote:

> _>Он объяснил <http://rsdn.ru/forum/?mid=2059607&gt;
Автор: Cyberax
Дата: 15.08.06
, что то, что делает

> С++ автоматически, тебе придётся делать
> _>тоже самое вручную, к тому же только хуже, т.к. у тебя нет контроля
> стека, какой есть у С++ компилятора.
> _>С++ лишь увеличивает размер бинарника под таблицы раскрутки, а в С будет
>
> _>дополнительный исполняемый код, что замедлит в итоге.
> <http://rsdn.ru/forum/?mid=2059458&gt;
Автор: Cyberax
Дата: 15.08.06

>
> Обычная задача оптимизации (как быстрее реализовать 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]: Скорость работы с использованием классов и без
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.08.06 17:58
Оценка:
Здравствуйте, remark, Вы писали:
R>Но большинство других функций не принимают размер.
Как правило, это те функции, которые не выиграют от знания размера. У них алгоритм устроен так, что последовательное сканирование их вполне устраивает.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Переформулируем вопрос
От: Cyberax Марс  
Дата: 15.08.06 19:44
Оценка:
MShura wrote:
> C>Ну так это и есть ручная эмуляция исключений.
> C>В данном случае С++ будет БЫСТРЕЕ, так как не надо проверять коды
> возврата.
> Не вижу разницы если проект на C использует структурные исключения
> вместо кодов возврата.
Для SEH нужно делать настройки каждого фрейма функции. Для исключений
С++ — необязательно.

> C++ вызывает throw а в C RaiseException.

> Если вы про new vs malloc, то элементарно сделать, чтобы malloc кидал
> структурное исключение.
> Писанины больше, но и вся разница.
> Кроме того, в структурных исключениях есть возможность продолжить
> выполнение с места исключения.
1. Где у нас SEH на Линуксе?
2. Как сделать SEH с zero-overhead по скорости?
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[12]: Переформулируем вопрос
От: Cyberax Марс  
Дата: 15.08.06 19:49
Оценка: +2
MShura wrote:
> Как показал сам Cyberax можно сделать несколько меток в конце функции
> (если ресурсы захватываются последовательно а именно так и происходит в
> большинстве функций), что убирает необходимость в дополнительных проверках.
> Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle
> все равно проверяется перед вызовом CloseHandle.
Я вообще-то просил сказать чем это отличается от семантики
автоматических деструкторов (ответ: почти ничем).

> Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал,

> что современные компиляторы умеют нивелировать *косвенный* вызов
> функции, что уж говорить об обычном ветвлении. К тому же есть подсказки
> компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу.
Ну тогда какие вопросы к С++, который просто при инициализации объекта
устанавливает флаг?

> Одним словом я бы не стал категорично заявлять, что код освобождения

> ресурсов в C больше оного в C++.
Больше. В С++ с умными указателями тот же код:
scoped_array<char> arr1(new char[...]);
scoped_array<char> arr2(new char[...]);

Все! Причем нельзя забыть поставить cleanup в конце.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[13]: Переформулируем вопрос
От: MShura  
Дата: 16.08.06 09:38
Оценка:
>>
>> Обычная задача оптимизации (как быстрее реализовать 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++.
_>В лучшем случае такой же, но никак не меньше. За счёт чего может быть меньше?
Имелось в в виду не написанный, а сгенеренный код.
Re[13]: Переформулируем вопрос
От: MShura  
Дата: 16.08.06 10:11
Оценка: 4 (1)
>> Как показал сам Cyberax можно сделать несколько меток в конце функции
>> (если ресурсы захватываются последовательно а именно так и происходит в
>> большинстве функций), что убирает необходимость в дополнительных проверках.
>> Если у Вас обертка над открытым HANDLE, то в деструкторе значение handle
>> все равно проверяется перед вызовом CloseHandle.
C>Я вообще-то просил сказать чем это отличается от семантики
C>автоматических деструкторов (ответ: почти ничем).

>> Есть конечно экзотические ситуации, однако тот же Cyberax меня убеждал,

>> что современные компиляторы умеют нивелировать *косвенный* вызов
>> функции, что уж говорить об обычном ветвлении. К тому же есть подсказки
>> компилятору likely,unlikely (в gcc), которые еще нивелируют эту разницу.
C>Ну тогда какие вопросы к С++, который просто при инициализации объекта
C>устанавливает флаг?
Отвечаю на два вопроса.
В C можно никаких дополнительных переменных (неявных) не заводить.

>> Одним словом я бы не стал категорично заявлять, что код освобождения

>> ресурсов в C больше оного в C++.
C>Больше. В С++ с умными указателями тот же код:
C>
C>scoped_array<char> arr1(new char[...]);
C>scoped_array<char> arr2(new char[...]);
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;
}


Компилим: cl /c /O2 /EHs /GX /FAs tst.cpp
Версия компилятора 13.10.3052.

Можно смотреть сгенеренный asm, а можно воспользоваться помощью IDA.

Вот код Функции TestC

.text:00000000 ; int __cdecl TestC(void)
.text:00000000                 push    ebx
.text:00000001                 push    edi
.text:00000002                 push    64h ; 'd'
.text:00000004                 mov     ebx, 0FFFFFFF4h
.text:00000009                 call    _malloc
.text:0000000E                 mov     edi, eax
.text:00000010                 add     esp, 4
.text:00000013                 test    edi, edi
.text:00000015                 jz      short loc_44
.text:00000017                 push    esi
.text:00000018                 push    64h ; 'd'
.text:0000001A                 call    _malloc
.text:0000001F                 mov     esi, eax
.text:00000021                 add     esp, 4
.text:00000024                 test    esi, esi
.text:00000026                 jz      short loc_3A
.text:00000028                 push    esi
.text:00000029                 push    edi
.text:0000002A                 call    ?FuncC@@YAIPAD0@Z ; FuncC(char *,char *)
.text:0000002F                 push    esi
.text:00000030                 mov     ebx, eax
.text:00000032                 call    _free
.text:00000037                 add     esp, 0Ch
.text:0000003A 
.text:0000003A loc_3A:                                 ; CODE XREF: TestC(void)+26j
.text:0000003A                 push    edi
.text:0000003B                 call    _free
.text:00000040                 add     esp, 4
.text:00000043                 pop     esi
.text:00000044 
.text:00000044 loc_44:                                 ; CODE XREF: TestC(void)+15j
.text:00000044                 pop     edi
.text:00000045                 mov     eax, ebx
.text:00000047                 pop     ebx
.text:00000048                 retn
.text:00000048 ?TestC@@YAHXZ   endp
.text:00000048 
.text:00000048 _text           ends


Вот код функции TestCpp и её окружения
               Зачем здесь сгенерен конструктор?
.text:0000004A ; public: __thiscall std::auto_ptr<char>::auto_ptr<char>(char *)
.text:0000004A arg_0           = dword ptr  4
.text:0000004A 
.text:0000004A                 mov     eax, ecx
.text:0000004C                 mov     ecx, [esp+arg_0]
.text:00000050                 mov     [eax], ecx
.text:00000052                 retn    4
.text:00000052 ??0?$auto_ptr@D@std@@QAE@PAD@Z endp
.text:00000052 
.text:00000052 _text           ends
.text:00000052 
.text:00000056 
.text:00000056 ; public: __thiscall std::auto_ptr<char>::~auto_ptr<char>(void)
.text:00000056                 mov     eax, [ecx]
.text:00000058                 push    eax
.text:00000059                 call    ??3@YAXPAX@Z    ; operator delete(void *)
.text:0000005E                 pop     ecx
.text:0000005F                 retn
.text:0000005F ??1?$auto_ptr@D@std@@QAE@XZ endp
.text:0000005F 
.text:0000005F _text           ends
.text:0000005F 
.text:00000060 ; void __cdecl TestCpp(void)
.text:00000060 
.text:00000060 var_14          = dword ptr -14h
.text:00000060 var_10          = dword ptr -10h
.text:00000060 var_C           = dword ptr -0Ch
.text:00000060 var_4           = dword ptr -4
.text:00000060 
.text:00000060                 push    0FFFFFFFFh
.text:00000062                 push    offset __ehhandler$?TestCpp@@YAXXZ
.text:00000067                 mov     eax, dword ptr fs:__except_list
.text:0000006D                 push    eax
.text:0000006E                 mov     dword ptr fs:__except_list, esp
.text:00000075                 sub     esp, 8
.text:00000078                 push    64h ; 'd'
.text:0000007A                 call    ??_U@YAPAXI@Z
.text:0000007F                 mov     [esp+18h+var_10], eax
.text:00000083                 push    64h ; 'd'
.text:00000085                 mov     [esp+1Ch+var_4], 0            <--- Что это за переменная?
.text:0000008D                 call    ??_U@YAPAXI@Z
.text:00000092                 mov     [esp+1Ch+var_14], eax
.text:00000096                 lea     eax, [esp+1Ch+var_14]
.text:0000009A                 push    eax
.text:0000009B                 lea     ecx, [esp+20h+var_10]
.text:0000009F                 push    ecx
.text:000000A0                 mov     byte ptr [esp+24h+var_4], 1    <--- Что это за переменная?
.text:000000A5                 call    ?FuncCpp@@YAXAAV?$auto_ptr@D@std@@0@Z ; FuncCpp(std::auto_ptr<char> &,std::auto_ptr<char> &)
.text:000000AA                 mov     edx, [esp+24h+var_14]
.text:000000AE                 push    edx
.text:000000AF                 call    ??3@YAXPAX@Z    ; operator delete(void *)
.text:000000B4                 mov     eax, [esp+28h+var_10]
.text:000000B8                 push    eax
.text:000000B9                 call    ??3@YAXPAX@Z    ; operator delete(void *)
.text:000000BE                 mov     ecx, [esp+2Ch+var_C]
.text:000000C2                 mov     dword ptr fs:__except_list, ecx
.text:000000C9                 add     esp, 2Ch
.text:000000CC                 retn
.text:000000CC ?TestCpp@@YAXXZ endp
.text:000000CC 
.text:000000CC _text           ends
.text:000000CC 
.text$x:000000CE 
.text$x:000000CE $L48140         proc near               ; DATA XREF: .xdata$x:000000ECo
.text$x:000000CE                 lea     ecx, [ebp-10h]
.text$x:000000D1                 jmp     ??1?$auto_ptr@D@std@@QAE@XZ ; std::auto_ptr<char>::~auto_ptr<char>(void)
.text$x:000000D1 $L48140         endp
.text$x:000000D1 
.text$x:000000D6 
.text$x:000000D6 $L48141         proc near               ; DATA XREF: .xdata$x:000000F4o
.text$x:000000D6                 lea     ecx, [ebp-14h]
.text$x:000000D9                 jmp     ??1?$auto_ptr@D@std@@QAE@XZ ; std::auto_ptr<char>::~auto_ptr<char>(void)
.text$x:000000D9 $L48141         endp
.text$x:000000D9 
.text$x:000000DE 
.text$x:000000DE __ehhandler$?TestCpp@@YAXXZ proc near   ; DATA XREF: TestCpp(void)+2o
.text$x:000000DE                 mov     eax, offset $T48161
.text$x:000000E3                 jmp     ___CxxFrameHandler
.text$x:000000E3 __ehhandler$?TestCpp@@YAXXZ endp
.text$x:000000E3 
.text$x:000000E3 _text$x         ends
.text$x:000000E3 
.xdata$x:000000E8 ; ===========================================================================
.xdata$x:000000E8 
.xdata$x:000000E8 ; Segment type: Pure data
.xdata$x:000000E8 _xdata$x        segment dword public 'DATA' use32
.xdata$x:000000E8                 assume cs:_xdata$x
.xdata$x:000000E8                 ;org 0E8h
.xdata$x:000000E8 $T48164         dd 0FFFFFFFFh           ; DATA XREF: .xdata$x:00000100o
.xdata$x:000000EC                 dd offset $L48140
.xdata$x:000000F0                 dd 0
.xdata$x:000000F4                 dd offset $L48141
.xdata$x:000000F8 $T48161         dd 19930520h            ; DATA XREF: __ehhandler$?TestCpp@@YAXXZo
.xdata$x:000000FC                 dd 2
.xdata$x:00000100                 dd offset $T48164
.xdata$x:00000104                 dd 0
.xdata$x:00000108                 dd 0
.xdata$x:0000010C                 dd 0
.xdata$x:00000110                 dd 0
.xdata$x:00000110 _xdata$x        ends



Считаем:
Код функции TestC: 0x4A
Код Функции TestCpp: 0xCE-0x60 = 0x6E
auto_ptr<char>::~auto_ptr<char> : 0x60-0x56 = 0xA
два освободителя 0xDE-0xCE = 0x10
код раскрутки стека: 0xE3 — 0xDE = 5
таблицы: 0x110 — 0xE8 = 0x28

Итого 74 байта vs 181.
Плюс глубина использования стека 0x20 vs 0x2С
Re[14]: Переформулируем вопрос
От: FR  
Дата: 16.08.06 10:41
Оценка:
Здравствуйте, MShura, Вы писали:


MS>Конечно код написанный программистом на C++ будет меньше в текстовом виде, но больше в двоичном.


Фигня, скорость будет практически одинаковой.

MS>пример:


там у тебя ошибка в auto_ptr нельзя давать new []
Re[14]: Переформулируем вопрос
От: kan_izh Великобритания  
Дата: 16.08.06 13:25
Оценка: 4 (1)
MShura wrote:

Лажа какая-то. Вот мой асм:
PUBLIC    ?TestC@@YAHXZ                    ; TestC
EXTRN    _free:NEAR
EXTRN    _malloc:NEAR
; Function compile flags: /Ogty
;    COMDAT ?TestC@@YAHXZ
_TEXT    SEGMENT
?TestC@@YAHXZ PROC NEAR                    ; TestC, COMDAT

; 30   : {

    push    esi
    push    edi

; 31   :   int err = -ENOMEM;
; 32   :   char* a, *b;
; 33   :
; 34   :   a = (char*)malloc( 100 );

    push    100                    ; 00000064H
    mov    esi, -12                ; fffffff4H
    call    _malloc
    mov    edi, eax
    add    esp, 4

; 35   :   if ( NULL == a )

    test    edi, edi
    je    SHORT $L10293

; 36   :     goto end1;
; 37   :
; 38   :   b = (char*)malloc( 100 );

    push    100                    ; 00000064H
    call    _malloc
    add    esp, 4

; 39   :   if ( NULL == b )

    test    eax, eax
    je    SHORT $end2$8985

; 40   :     goto end2;
; 41   :
; 42   :   err = FuncC( a, b );
; 43   :
; 44   :   free( b );

    push    eax
    xor    esi, esi
    call    _free
    add    esp, 4
$end2$8985:

; 45   : end2:
; 46   :   free( a );

    push    edi
    call    _free
    add    esp, 4
$L10293:
    pop    edi

; 47   : end1:
; 48   :   return err;

    mov    eax, esi
$end1$8981:
    pop    esi

; 49   : }

    ret    0
?TestC@@YAHXZ ENDP                    ; TestC


?TestCpp@@YAXXZ PROC NEAR                ; TestCpp, COMDAT

; 12   : {

    push    -1
    push    __ehhandler$?TestCpp@@YAXXZ
    mov    eax, DWORD PTR fs:__except_list
    push    eax
    mov    DWORD PTR fs:__except_list, esp
    push    ecx
    push    esi

; 13   :     std::auto_ptr<char> a ( new char [100] );

    push    100                    ; 00000064H
    call    ??_U@YAPAXI@Z                ; operator new[]
    mov    esi, eax
    mov    DWORD PTR _a$[esp+24], esi

; 14   :     std::auto_ptr<char> b ( new char [100] );

    push    100                    ; 00000064H
    mov    DWORD PTR __$EHRec$[esp+36], 0
    call    ??_U@YAPAXI@Z                ; operator new[]

; 15   :     FuncCpp( a, b );
; 16   : }

    push    eax
    call    ??3@YAXPAX@Z                ; operator delete
    push    esi
    call    ??3@YAXPAX@Z                ; operator delete
    mov    ecx, DWORD PTR __$EHRec$[esp+36]
    add    esp, 16                    ; 00000010H
    pop    esi
    mov    DWORD PTR fs:__except_list, ecx
    add    esp, 16                    ; 00000010H
    ret    0
_TEXT    ENDS
;    COMDAT text$x
text$x    SEGMENT
$L10399:
    lea    ecx, DWORD PTR _a$[ebp]
    jmp    ??1?$auto_ptr@D@std@@QAE@XZ        ; std::auto_ptr<char>::~auto_ptr<char>
__ehhandler$?TestCpp@@YAXXZ:
    mov    eax, OFFSET FLAT:$T10423
    jmp    ___CxxFrameHandler
text$x    ENDS
?TestCpp@@YAXXZ ENDP                    ; TestCpp

Т.е. кода обработки ошибок НЕТ вообще! Т.е. С++ код в отсутсвие исключений даже ПРОЩЕ, чем С код. Есть пролог и эпилог
функции, которые не содежрат условных операторов и переходов (хотя за счёт увеличения стека). И 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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.