Re[10]: Как вы реально работаете с памятью в C++?
От: о_О
Дата: 07.01.11 17:42
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

очередной круг спецзабега рсдн? okay

PD>Хм, а что тут неэффективно и неправильно ?

PD>И в конце концов, неужели всеми уважаемый автор, признанный классик ИТ, будет писать в руководстве неэффективный и неправильный код. Зачем ему на позор себя выставлять ?

в той самой книге есть ошибки. порой нехорошие. кстати мыщъх их разбирал даже

PD>А то, что он демонстрационный — так и все, что там есть, демонстрационное. Там примеры того, как можно делать. А реальный код будет сложнее, конечно.


не буду комментировать

PD>И еще один вопрос, подумай. __finally в С появилось вместе с Win32. То есть это примерно так 1992-3 год.

PD>Ява будет позже. C# — еще позже. А там эти конструкции штатные. Авторы Явы MS не очень любят, зачем же они тогда эту конструкцию в Яву ввели ?

в яве полный 0, но догадываюсь что, как и в шарпе, это из-за использования исключений вместо кодов возврата. что вкупе с архитектурой и высокой абстракцией просто необходимо
Re[9]: раз уш так пошло
От: Pavel Dvorkin Россия  
Дата: 07.01.11 17:48
Оценка:
Здравствуйте, igna, Вы писали:

I>Это нормально, если для получения n-го ресурса нужно сначала получить (n-1)-ый для всех n в интервале от 2 до 5. Вложенность показывает, какой ресурс от какого зависит.


Я готов согласиться (с ограничениями), что это еще можно признать нормальным, когда речь идет о вложенности. А если не о вложенности ?


HDC hdc = GetDC(...);
HPEN hPen = CreatePen(...);
HBITMAP hBmp = LoadBitmap(...);
HANDLE hFile = CreateFile(...);


Тасуй эти строчки как хочешь — они независимы друг от друга. Стоять рядом им совсем не обязательно. А теперь представь себе, что вначале берется HDC, потом при каких-то услоовиях создается перо (а может, и не создается), потом в каком-то другом месте загружается битовая карта (а как там с пером — а бог его знает), потом где-то файл открывается, а может, и нет, потом все это в цикле оказывается, кроме GetDC, и при разных проходах цикла действия раздичны, а потом...


PD>>И всегда есть риск забыть про очистку, сделав где-то return в тот момент, когда абсолютно уверен, что отсюда надо выходить, а про очистку и не думаешь. И пишешь автоматически return — 1, и привет!


I>Ну наверное когда пишут функции, в которых логика управления ресурсами или еще что завязано на то, что выход из функции осуществляется одним единственным return (находящимся как правило в конце тела функции), использование return в других местах является табу.


Я бы не хотел дискутировать на эту тему, просто скажу — для меня это табу не является. все аргументы я слышал, но не считаю их убедительными.

>Тут не должно быть никакой автоматики. Так ведь кто-то и твое любимое третье решение Рихтера может испоганить, если "автоматически" запросит и освободит какой-либо новый ресурс не в соответствии с использованным там паттерном.


А это невозможно, в том то и дело.

Новый ресурс ? Пожалуйста



HRESOURCE hRsrc = 0; 

__finally
{
  if(hRsrc !=0)
   DeleteResource(hRsrc);
}
With best regards
Pavel Dvorkin
Re[11]: Как вы реально работаете с памятью в C++?
От: о_О
Дата: 07.01.11 17:48
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, о_О, Вы писали:


PD>>>Естественно, ничего личного.


о_О>>ололо павел, я то думал вы Капитан Политкорректность, или хотя бы додумаетесь, в вашем-то возрасте, подобное не комментировать...


PD>Просто тут есть личности, которые могут все принять на свой счет, ну я на всякий случай из извинился


особенно здорово если учитывать, что мой пост был в вашу пользу
Re[11]: Как вы реально работаете с памятью в C++?
От: Pavel Dvorkin Россия  
Дата: 07.01.11 17:51
Оценка: :)
Здравствуйте, о_О, Вы писали:

о_О>в той самой книге есть ошибки. порой нехорошие. кстати мыщъх их разбирал даже


От ошибок никто не застрахован, но одно дело — ошибка, а другое — предлагать порочное решение.

о_О>в яве полный 0, но догадываюсь что, как и в шарпе, это из-за использования исключений вместо кодов возврата. что вкупе с архитектурой и высокой абстракцией просто необходимо


Если мы начнем еще дискуссию на тему "исключения против кодов возврата" — кончим ее не скоро. Предлагаю не начинать
With best regards
Pavel Dvorkin
Re[12]: раз уш так пошло
От: о_О
Дата: 07.01.11 17:52
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, о_О, Вы писали:


о_О>>goto. и никакого SEH. вы против goto? вы просто не умеете его готовить


PD>С goto будут те же проблемы. return, break, continue, goto...


PD>А готовить goto я умею. Я лет 10 писал на Фортране-4, в котором не было цикла, кроме как с индексом. Так что циклов с помощью GOTO я немало написал.


вот это как раз и есть проявление профессиональных качеств/навыков — избегать подобных "а что если"
иногда на обдумывание уходит 90% времени, а на написание 10%. зато потом из проекта в проект банальный копи-паст
Re[12]: Как вы реально работаете с памятью в C++?
От: Pavel Dvorkin Россия  
Дата: 07.01.11 17:58
Оценка:
Здравствуйте, о_О, Вы писали:


PD>>Просто тут есть личности, которые могут все принять на свой счет, ну я на всякий случай из извинился


о_О>особенно здорово если учитывать, что мой пост был в вашу пользу


With best regards
Pavel Dvorkin
Re[13]: раз уш так пошло
От: Pavel Dvorkin Россия  
Дата: 07.01.11 17:59
Оценка:
Здравствуйте, о_О, Вы писали:

PD>>А готовить goto я умею. Я лет 10 писал на Фортране-4, в котором не было цикла, кроме как с индексом. Так что циклов с помощью GOTO я немало написал.


о_О>вот это как раз и есть проявление профессиональных качеств/навыков — избегать подобных "а что если"

о_О>иногда на обдумывание уходит 90% времени, а на написание 10%.

Совершенно верно.

>зато потом из проекта в проект банальный копи-паст


Именно. Но боюсь, за копи-паст на тебя сейчас набросятся
With best regards
Pavel Dvorkin
Re[12]: Как вы реально работаете с памятью в C++?
От: о_О
Дата: 07.01.11 18:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Если мы начнем еще дискуссию на тему "исключения против кодов возврата" — кончим ее не скоро. Предлагаю не начинать


идея на день, когда флейма станет мало

кстати вспомнил, что в яве goto и нет
Re[13]: Как вы реально работаете с памятью в C++?
От: Pavel Dvorkin Россия  
Дата: 07.01.11 18:09
Оценка:
Здравствуйте, о_О, Вы писали:

о_О>кстати вспомнил, что в яве goto и нет


У меня к goto сложное отношение.

Привык к нему за фортрановские годы. А потом пересел на Паскаль. А там он есть, но использование его — дурной тон вроде. А я привык. Надо отвыкать. И отвык. Через несколько лет понял, что мне его и употреблять не хочется.

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

KISS


Кстати. Во времена Win16 попался мне как-то исходник DefWindowProc, ее тогда опубликовали. Там goto было не мало, но один ме очень понравился

goto ICantBelieveThatIUsedGoToStatement;


Вот goto назад — это ИМХО действительно зло. goto назад — это цикл, а раз так, будьте добры оператор цикла и используйте.
With best regards
Pavel Dvorkin
Re[14]: раз уш так пошло
От: о_О
Дата: 07.01.11 18:11
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

>>зато потом из проекта в проект банальный копи-паст


PD>Именно. Но боюсь, за копи-паст на тебя сейчас набросятся


как набросятся так и отбросятся. если моё первое сообщение неделю назад, это не значит ничего
Re[14]: Как вы реально работаете с памятью в C++?
От: о_О
Дата: 07.01.11 18:30
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>У меня к goto сложное отношение.


PD>Привык к нему за фортрановские годы. А потом пересел на Паскаль. А там он есть, но использование его — дурной тон вроде. А я привык. Надо отвыкать. И отвык. Через несколько лет понял, что мне его и употреблять не хочется.


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


я соглашусь, что goto надо избегать, но не запрещать. более того, применять его сложно. особенно НЕ в ущерб чего-либо

PD>Вот goto назад — это ИМХО действительно зло. goto назад — это цикл, а раз так, будьте добры оператор цикла и используйте.


а что скажете вот о таком? как тут без goto?
uint TTabber::_NewItemId() const
{
    uint res;

    again:
    res = _ItemIdGen();
    for (SizeT n = 0; n < _ItemList.size(); n++)
        if (res == _ItemList[n]->ID) goto again;
    
    return res;
}
//при внимательном прочтении вроде всё и так ясно
Re[15]: Как вы реально работаете с памятью в C++?
От: Pavel Dvorkin Россия  
Дата: 07.01.11 18:56
Оценка:
Здравствуйте, о_О, Вы писали:


о_О>а что скажете вот о таком? как тут без goto?

о_О>
о_О>uint TTabber::_NewItemId() const
о_О>{
о_О>    uint res;

о_О>    again:
о_О>    res = _ItemIdGen();
о_О>    for (SizeT n = 0; n < _ItemList.size(); n++)
о_О>        if (res == _ItemList[n]->ID) goto again;
    
о_О>    return res;
о_О>}
о_О>//при внимательном прочтении вроде всё и так ясно
о_О>


Примерно так. Естественно, за возможное зацикливание я не отвечаю.

bool bNotFound = false;// на чистом С замени на char = 0;
while(!bNotFound) 
{
 SizeT size = _ItemList.size(); // может, вынести из цикла, если размер не меняется
 res = _ItemIdGen();
 bNotFound = false; 
 for (SizeT n = 0; n < size ;n++)
  if (res == _ItemList[n]->ID) 
   break;
 if(n == size)
 bNotFound = true;
}
With best regards
Pavel Dvorkin
Re[16]: Как вы реально работаете с памятью в C++?
От: о_О
Дата: 07.01.11 19:13
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Примерно так


в сравнении ужасно, не правда ли? :3
Re[2]: Как вы реально работаете с памятью в C++?
От: Kerbadun  
Дата: 08.01.11 00:36
Оценка:
Здравствуйте, blackhearted, Вы писали:

K>>4) Используете garbage collector? Но он же точным быть не может? А производительность? А кроссплатформенность?

B>А это тут при чём? Что за точность?

Про точность я ошибался. Для C++ существуют точные сборщики мусора (хотя для C++ сборка мусора — вещь все равно условная, так как она принципиально не может быть эффективной).

B>Где вам не хватает перформанса? Вы покажите.


Просто хотелось узнать, как народ делает в своих программах, чтобы сделать выводы. А то вдруг я чего-то не знал? Пока что ничего нового не предложили.

Когда он умрет, его мозг заспиртуют в стакане
Re[2]: Как вы реально работаете с памятью в C++?
От: Kerbadun  
Дата: 08.01.11 00:36
Оценка:
Здравствуйте, gegMOPO4, Вы писали:

K>>Как вы реально работаете с памятью в C++?

MOP>А вы как реально с числами работаете? Складываете их, отнимаете, умножаете или делите? Зависит от задачи.

Похоже, для C++-программиста это естественный ответ. Программисты на большинстве других языков так не думают.

В идеале, по крайней мере, в 99% выделение памяти вполне даже может быть полностью автоматическим, без всякой необходимости со стороны программиста думать о том, где как что выделяется и как отслеживается. Оставшийся 1% остается на случаи, когда предъявляются повышенные требования к производительности.

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

Когда он умрет, его мозг заспиртуют в стакане
Re[4]: Как вы реально работаете с памятью в C++?
От: jazzer Россия Skype: enerjazzer
Дата: 08.01.11 04:12
Оценка: :)
Здравствуйте, Pavel Dvorkin, Вы писали:

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


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


PD>>>Часто использую __try — __finally

PD>Просто я порой пишу на С

Это ты, конечно, молодец, но вопрос был "Как вы реально работаете с памятью в C++?"
Причем тут техники Си
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Как вы реально работаете с памятью в C++?
От: Pavel Dvorkin Россия  
Дата: 08.01.11 07:01
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Это ты, конечно, молодец, но вопрос был "Как вы реально работаете с памятью в C++?"

J>Причем тут техники Си

Так вроде и в С++ такое писать не запрещено. Или ты считаешь, что если уж С++ — так обязательно всякие auto_ptr и boost::something ?
With best regards
Pavel Dvorkin
Re[10]: раз уш так пошло
От: igna Россия  
Дата: 08.01.11 08:16
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>HDC hdc = GetDC(...);
PD>HPEN hPen = CreatePen(...);
PD>HBITMAP hBmp = LoadBitmap(...);
PD>HANDLE hFile = CreateFile(...);


PD>Тасуй эти строчки как хочешь — они независимы друг от друга. Стоять рядом им совсем не обязательно. А теперь представь себе, что вначале берется HDC, потом при каких-то услоовиях создается перо (а может, и не создается), потом в каком-то другом месте загружается битовая карта (а как там с пером — а бог его знает), потом где-то файл открывается, а может, и нет, потом все это в цикле оказывается, кроме GetDC, и при разных проходах цикла действия раздичны, а потом...


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

if (hdc && hPen && hBmp && hFile) {

    . . .

}

if (hFile)
    CloseHandle(hFile);
if (hBmp)
    CloseHandle(hBmp);
if (hPen)
    CloseHandle(hPen);
if (hdc)
    CloseHandle(hFile);


А это есть перенесение логики, которую может обработать компилятор, в рантайм. На мой взгляд лучше уж отступы или goto:

if (!(hdc = GetDC(...)))
    goto end;
if (!(hPen = CreatePen(...)))
    goto end_hdc;
if (!(hBmp = LoadBitmap(...)))
    goto end_hPen;
if (!(hFile = CreateFile(...)))
    goto end_hBmp;

. . .

end_hFile:
    CloseHandle(hFile);
end_hBmp:
    CloseHandle(hBmp);
end_hPen:
    CloseHandle(hPen);
end_hdc:
    CloseHandle(hFile);
end:


Но тут конечно есть свои недостатки по сравнению с __try/__finally, поэтому я возвращаю дискуссию к первому варианту (с проверками и без goto). Он то чем хуже?

PD>Я бы не хотел дискутировать на эту тему, просто скажу — для меня это табу не является. все аргументы я слышал, но не считаю их убедительными.


Хорошо. На всякий случай все же замечу, что я не про запрет на несколько операторов return в общем случае, а про конкретную функцию, логика которой требует, чтобы return находился в одном месте.

PD>А это невозможно, в том то и дело.

PD>Новый ресурс ? Пожалуйста


PD>HRESOURCE hRsrc = 0; 

PD>__finally
PD>{
PD>  if(hRsrc !=0)
PD>   DeleteResource(hRsrc);
PD>}


Почему же невозможно? Вот именно вместо освобождения ресурса в __finally освободить его где-то в другом месте.
Re[11]: раз уш так пошло
От: Pavel Dvorkin Россия  
Дата: 08.01.11 09:03
Оценка: 2 (1)
Здравствуйте, igna, Вы писали:

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


I>
PD>>HDC hdc = GetDC(...);
PD>>HPEN hPen = CreatePen(...);
PD>>HBITMAP hBmp = LoadBitmap(...);
PD>>HANDLE hFile = CreateFile(...);
I>


PD>>Тасуй эти строчки как хочешь — они независимы друг от друга. Стоять рядом им совсем не обязательно. А теперь представь себе, что вначале берется HDC, потом при каких-то услоовиях создается перо (а может, и не создается), потом в каком-то другом месте загружается битовая карта (а как там с пером — а бог его знает), потом где-то файл открывается, а может, и нет, потом все это в цикле оказывается, кроме GetDC, и при разных проходах цикла действия раздичны, а потом...


I>Потом ты берешь и проверяешь наличие всех необходимых ресурсов и выполняешь работу только при их наличии.


Ресурсы эти независимы, и работа с каждым ресурсом не обязательно зависит от успешности создания остальных. Мне тут все равно.

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


I>
I>if (hFile)
I>    CloseHandle(hFile);
I>if (hBmp)
I>    CloseHandle(hBmp);
I>if (hPen)
I>    CloseHandle(hPen);
I>if (hdc)
I>    CloseHandle(hFile);
I>


Да, только не надо WIN API CloseHandle применять к hBmp . Извини за занудство.

I> А это есть перенесение логики, которую может обработать компилятор, в рантайм. На мой взгляд лучше уж отступы или goto:


I>
I>if (!(hdc = GetDC(...)))
I>    goto end;
I>if (!(hPen = CreatePen(...)))
I>    goto end_hdc;
I>if (!(hBmp = LoadBitmap(...)))
I>    goto end_hPen;
I>if (!(hFile = CreateFile(...)))
I>    goto end_hBmp;

I>. . .

I>end_hFile:
I>    CloseHandle(hFile);
I>end_hBmp:
I>    CloseHandle(hBmp);
I>end_hPen:
I>    CloseHandle(hPen);
I>end_hdc:
I>    CloseHandle(hFile);
I>end:
I>


Ты меня не понял. Неудача в открытии каког-то ресурса в моем примере — не всегда основание для прекращения работы. Может да, а может и нет. Здесь нет вложенного доступа к ресурсам. Если я не смогу загрузить битмэп, то открою файл. А если смогу ее загрузить — может, тоже открою файл. Никаких предположений делать не надо о том, когда я продолжу или выйду и почему.

I>Но тут конечно есть свои недостатки по сравнению с __try/__finally, поэтому я возвращаю дискуссию к первому варианту (с проверками и без goto). Он то чем хуже?


А просто тем, что я вскоре потеряю представление, что и когда я должен закрывать

HDC получили
перо не создалось
битовую карту не создали
Может, надо выйти, а может, нет. Если надо — что закрывать ?
А если нет открываем файл. Успешно
а в файле информация о битовой карте. Откроем-ка заново. Успешно
И тут выяснилось, что карта не та. Может, надо выйти, а может, нет. Если да — что закрывать ?
А если нет — надо карту закрыть. И вновь попробовать создать перо
И вот сюда пришли. И что тут закрывать и что нет ? Я уже совершенно не понимаю, что я открыл и что нет, и что надо закрывать, а что нет.


I>Хорошо. На всякий случай все же замечу, что я не про запрет на несколько операторов return в общем случае, а про конкретную функцию, логика которой требует, чтобы return находился в одном месте.


А когда логика это требует и когда не требует ?

PD>>А это невозможно, в том то и дело.

PD>>Новый ресурс ? Пожалуйста

I>

PD>>HRESOURCE hRsrc = 0; 

PD>>__finally
PD>>{
PD>>  if(hRsrc !=0)
PD>>   DeleteResource(hRsrc);
PD>>}

I>


I>Почему же невозможно? Вот именно вместо освобождения ресурса в __finally освободить его где-то в другом месте.


На здоровье. Только освобождать надо так

DeleteResource(hRsrc);
hRscrc = 0;



В Delphi есть специальная функция FreeAndNil.

Вообще у меня правило такое. Рабочие переменные (те, которые на 2-3 строчки нужны) можно бросить после использования в неопределенном состоянии. Для чего-то более серьезного состояние должно всегда быть определенным. Если это дескриптор — пусть он будет !=0 пока он валиден, а удалили объект — присвойте ему 0. Указатель — аналогично.
With best regards
Pavel Dvorkin
Re[13]: раз уш так пошло
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 08.01.11 09:30
Оценка:
Здравствуйте, о_О, Вы писали:

о_О>>>goto. и никакого SEH. вы против goto? вы просто не умеете его готовить :xz:


PD>>С goto будут те же проблемы. return, break, continue, goto...


PD>>А готовить goto я умею. Я лет 10 писал на Фортране-4, в котором не было цикла, кроме как с индексом. Так что циклов с помощью GOTO я немало написал.


о_О>вот это как раз и есть проявление профессиональных качеств/навыков — избегать подобных "а что если"

о_О>иногда на обдумывание уходит 90% времени, а на написание 10%. зато потом из проекта в проект банальный копи-паст :xz:

Ну банального копи-паста по любому надо избегать. Хотя между проектами, наверно, пофиг. Вот в одном файле — может быть критичным. У нас как-то из-за такого патч наложился на другой участок кода (с fuzz'ом, но без полного отказа), последствия поймали только на тестировании вживую.

Но я не о том, а о goto. Собственно, начав с Фортрана, я тоже его люблю нежной любовью (во всех смыслах), причём даже такие суперхитрые варианты, как назначенный goto. Но с другой стороны — двухлетний опыт Erlang'а и шестилетний — Python'а приучил обходиться без него:) и надо заметить — это в принципе не сложно. Вопрос только в эффективности. В некоторых случаях (на процедурных языках без обработки исключений) приходилось строить вместо одной функции две — в первой создаётся набор переменных, передаётся во вторую, которая делает return по каждому чиху, затем в первой независимо от возвращённого значения делается зачистка и только тогда управление возвращается вызвавшему. Не скажу, что это выглядело симпатично — скорее, это было меньшее из всех возможных зол. Тогда я однозначно предпочёл бы goto, если бы он был доступен.
The God is real, unless declared integer.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.