Pull to refresh

Comments 15

«goto err_exit;»
Вы убили мозг моего внутреннего программиста!
Пожалуйста, во избежание травмирования мозга других хабраюзеров, поменяйте ЭТО на обычный «break;».
STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
//
//немного кода skipped
//
    HRESULT hr = NOERROR;

    if (!HIWORD(lpcmi->lpVerb)) 
    {
         idCmd = LOWORD(lpcmi->lpVerb);

         // process it
         switch (idCmd) 
         {
                default:
                    hr = E_INVALIDARG;
                    break;
                case 0: // operation 1
                case 1: // operation 2
//
//много кода skipped
//
                break;
         }    // switch on command
    }
   return hr;
}


Хотя бы так…
С этим кодом тоже проблемы. Нужно не забыть обработать ветку if — else

STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
//
//немного кода skipped
//
    HRESULT hr = NOERROR;

    if (!HIWORD(lpcmi->lpVerb)) 
    {
         idCmd = LOWORD(lpcmi->lpVerb);

         // process it
         switch (idCmd) 
         {
                default:
                    hr = E_INVALIDARG;
                    break;
                case 0: // operation 1
                case 1: // operation 2
//
//много кода skipped
//
                break;
         }    // switch on command
    }
    else
    {
        hr = E_INVALIDARG;
    }
   return hr;
}


А вообще да, goto это зло.

Просто я лично привык к goto с незапамятных времен школьного BASIC. Там без GOTO обойтись тяжело. Еще помню, была просто волшебная команда RENUMBER.
Да, согласен, писал второпях, желая пояснить суть своего негодования.

ЗЫ: сам начинал с васика, там были GOTO и GOSUB незаменимы.
А статью так и не обновили…
И молодёжь, не читающая комменты, будет думать, что goto это хорошо…
Ниже уже ответили, что goto это хорошо для обработки ошибок.
Да я и сам так всегда делаю, очень удобно. Вот пример кода:
int TestFunction(void)
{
    int result;
    char *Buffer=NULL;

    Buffer = (char *)ALLOC(MAX_BUFFER_LENGTH);
    if (Buffer == NULL)
    {
        result = ERR_MEM;
        goto err_exit;
    }

    result = DoSomeJob(Buffer);
    if (result) goto err_exit;

    result = DoAnotherJob(Buffer);
    if (result) goto err_exit;

    result = DoThirdJob(Buffer);

err_exit:
    if (Buffer) FREE(Buffer);
    return result;
}

Здесь всегда можно быть уверенным на 100% что не забудем сделать FREE.
А теперь попробуйте эту функцию реализовать без goto — скорее всего будет нечитаемо.
А чем try/catch/finally не угодил?
Собственно, для этих целей исключения и были придуманы.
Использование goto для перехода на обработчик ошибок — стандартная практика в C коде. Хотя код автора и на C++, написан он в стиле C.
Вот что бывает, когда вместо того, чтобы проанализировать чужой код, понять суть и сделать по-своему и правильно, тупо отключают мозг и копируют код.
Спасибо! Грандиозное спасибо! Вот оно! Вот из-за чего (CompareIt!) у меня «внезапно» отрубался «Запуск от имени Администратора» на ярлыках. Просто между установкой и обнаружением проблемы обычно проходило достаточно времени чтобы забыть о том что ставилось. Да и, признаться, никогда бы на нее не подумал. К тому же происходило это всего два раза (да, винду переставляю редко), поэтому статистику для анализа собрать пока не успел. Так и жил без «Запустить от имени Администратора», выкручивался посредством «Расположение файла» и «Запуск от Админа» уже непосредственно на экзешнике.
Теперь бы еще придумать чем заменить CompareIt! или как релизовать его глючащие «compare file #1» и «compare file #2» в обход, неглючным методом.
Обновил CompareIt!, проблема пропала. Как-то не следил за обновлениями, меня он полностью устраивал, вот и получил граблю :")
Да, правильно. «Запуск от имени Администратора» на ярлыках перестает работать — это тоже связано с некорректной обработкой ContextMenu. Нужно бы отдельную статью посвятить и этой проблеме тоже.

Можете ли еще подсказать, какая версия CompareIt! у Вас стояла, в которой наблюдалась ошибка?
Посмотрел. Была установлена 4.1.0.2170 (ей года три, наверное). После обновления до 4.2.0.2221 проблема устраниась. Теоретически должна помочь замена wincmpExt.dll(wincmpExt64.dll) на свежие версии (новые на два года моложе).
LPCMINVOKECOMMANDINFO lpcmi
Неужели кто-то ещё так именует типы переменных? Это же АДЪ И ИЗРАИЛЬ! Наверняка же есть обновленная версия API, где нет такого душераздирающего ужаса!
Типичное именование для WinAPI и COM на C++, смысл именовать иначе когда вокруг весь код и все API написаны придерживаясь такой конвенции — только путать будет.
Sign up to leave a comment.

Articles