Кресты / Говнокод #7818 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
HRESULT GetOutlookVersionString(LPSTR* ppszVer, BOOL* pf64Bit)
{
    HRESULT hr = E_FAIL;
    LPSTR pszTempPath = NULL;
    LPSTR pszTempVer = NULL;
    TCHAR pszaOutlookQualifiedComponents[][MAX_PATH] = {
        TEXT("{1E77DE88-BCAB-4C37-B9E5-073AF52DFD7A}"), // Outlook 2010
        TEXT("{24AAE126-0911-478F-A019-07B875EB9996}"), // Outlook 2007
        TEXT("{BC174BAD-2F53-4855-A1D5-0D575C19B1EA}")  // Outlook 2003
    };

    int nOutlookQualifiedComponents = _countof(pszaOutlookQualifiedComponents);
    int i = 0;
    DWORD dwValueBuf = 0;
    UINT ret = 0;

    *pf64Bit = FALSE;

    for (i = 0; i < nOutlookQualifiedComponents; i++)
    {
        ret = MsiProvideQualifiedComponent(
            pszaOutlookQualifiedComponents[i],
            TEXT("outlook.x64.exe"),
            (DWORD) INSTALLMODE_DEFAULT,
            NULL,
            &dwValueBuf);
        if (ERROR_SUCCESS == ret) break;
    }

    if (ret != ERROR_SUCCESS)
    {
        ret = MsiProvideQualifiedComponent(
            pszaOutlookQualifiedComponents[i],
            TEXT("outlook.exe"),
            (DWORD) INSTALLMODE_DEFAULT,
            NULL,
            &dwValueBuf);
    }
    else
    {
        *pf64Bit = TRUE;
    }

    if (ret == ERROR_SUCCESS)
    {
        dwValueBuf += 1;
        pszTempPath = (LPSTR) malloc(dwValueBuf * sizeof(TCHAR));

        if (pszTempPath != NULL)
        {
            if ((ret = MsiProvideQualifiedComponent(
                pszaOutlookQualifiedComponents[i],
                TEXT("outlook.exe"),
                (DWORD) INSTALLMODE_EXISTING,
                pszTempPath,
                &dwValueBuf)) != ERROR_SUCCESS)
            {
                goto Error;
            }

            pszTempVer = (LPSTR) malloc(MAX_PATH * sizeof(TCHAR));
            dwValueBuf = MAX_PATH;
            if ((ret = MsiGetFileVersion(pszTempPath,
                pszTempVer,
                &dwValueBuf,
                NULL,
                NULL))!= ERROR_SUCCESS)
            {
                goto Error;    
            }
            *ppszVer = pszTempVer;
            pszTempVer = NULL;
            hr = S_OK;
        }
    }

Error:
    free(pszTempVer);
    free(pszTempPath);
    return hr;
}

Говнокод от САМОГО Билли... 21 век на дворе, а у нас в C++ коде goto Error написано (точнее - накакано).
Источник - http://msdn.microsoft.com/en-us/library/dd941331.aspx

Запостил: kVolt kVolt, (Updated )

Комментарии (66) RSS

  • еще одна жертва "не за что не используйте goto в своих программах!"?
    Ответить
    • нет. жертва постоянного применения исключения из этого правила.
      Ответить
        • +1
          В MS коде везде так ошибки обрабатываются, это стало идиомой. Кроме того, такое использование goto приветствует Макконнелл: меньше дублирования кода.
          Ответить
              • throwExceptionByHResult(hr);
                По моему это лучше, чем
                if (ret == ERROR_SUCCESS)
                {
                  obj1->Release();
                  ...
                  onjn->Release();
                  goto err;
                };
                И так после вызова каждой функции.
                Ответить
                  • Это очень глупо, когда:
                    IUnknown *a, *b;
                    HRESULT r=makeComObject(&a,  guid1);
                    if(r!=ERROR_SUCCESS)
                      goto err;
                    r=makeComObject(&b,  guid2);
                    if(r!=ERROR_SUCCESS)
                      goto err;
                    ...
                    err:
                      a->Release();
                      b->Release();
                    Особенно с учетом того, что b ещё может быть не создан, когда мы входим в err. Поэтому, с такой практикой err приходится удалять все объекты вручную внутри if'а перед переходом goto err;.

                    Есть, конечно, реализации SafeRelease, но это костыль.

                    Гуглите реализацию ComPtr<IТипИнтерфейс> comObj.
                    Этот частный случай смартпоинтера сам вызовет Release, даже если неожиданно произойдет исключение. Да и работать с ним удобнее, чем с голым интерфейсом.
                    Ответить
                    • > Этот частный случай смартпоинтера сам вызовет Release

                      Я понимаю, что на РАИИ всё это делается вообще без усилий и само по себе.
                      Но если говорить про низкий уровень, то гото - лучший вариант. Ну и отдельно флаги, хранящие, кого мы созали, а кого-нет.
                      Ответить
                      • Вы про Си или про неправильное использование С++, за которое он иногда бьет по рукам?
                        Ответить
                        • Микрософт принипиально пишет системные функции без крестофишечек (и это правильно), так что будем говорить про Си.
                          Ответить
                          • Но использовать то системные функции можно и в С++. Си интерфейс системных библиотек не накладывает ограничений на код их использующий.

                            Даже системные функции можно на С++ писать, главное наружу выдавать Си интерфейс и не выпускать исключений.
                            Ответить
                            • > главное наружу выдавать Си интерфейс и не выпускать исключений

                              Это проще, если сразу всё на чистом Си писать.
                              Ответить
                              • На чистом Си никогда не было проще. В стандартной библиотеке Си даже высокоуровневых структур и примитивов нет. Приходится все вручную велосипедить.
                                Ответить
            • Если бы он был за дублирование, то он был бы
              Маконелмаконел
              А так он провёл оптимизацию и сделал так, что дублируются только три буквы.
              Ответить
            • >Странно, с такой фамилией и против дублирования.
              Ему пришлось иметь дело с наследованием старого кода
              Ответить
          • пчему не try / catch кстати, если уж мы про MS?
            Ответить
    • Не, это жертва копи-пейста. В последнем условии присваивание не нужно, но оно есть, потому что оно есть в 4 предыдущих условиях...
      Ответить
    • ответ на вопрос - по пруфлинку ) Судя по всему, MS искренне считает, так должен выглядеть тру-C++ код )
      Ответить
  • ERROR_SUCCESS - диалектический дуализм.
    Всегда доставляло число аргументов в API -функциях мелкомягких.
    Ответить
    • От слова Error, но признаю, странное идентификаторообразование у ms...
      Ответить
  • > Говнокод от САМОГО Билли
    Да ладно, всем понятно, что это написали индусы за чизбургер и баночку колы
    Ответить
  • Хм, а Билли программистом стал, очень весело. Хм, когда это Билли что-то программил?
    Ответить
  • Здесь прекрасно всё. Захардкоженный кабаллистический массив pszaOutlookQualifiedComponents. Гарантированный выход за его пределы в 33. Повторная проверка в 30 и 44. Ну и спагетти-код.
    Ответить
    • > Повторная проверка в 30 и 44
      ret между этими вызовами мог измениться (строка 32)

      в 30-42 вообще какой-то трэш происходит. Почему x64 версия проверяется для всех ключей, а x86 - не для всех?
      Ответить
      • Только в одной из веток после 30! Почему бы не засунуть другой if прямо туда? Вообще, если грамотно расписать структурно, так может никакие goto и не понадобились бы, и код стал бы читаться яснее.
        Ответить
  • Код нужно осовременить. Переписать с использованием try...catch.
    Ответить
      • тем более, что на этот костыль где то свой костыль прибит....нее....сцыкотно...вдруг сломается.... а так сразу видно, что если еррор - то иди на еррор, и никаких сусликов!
        Ответить
    • В такой низкоуровневый код исключения не влазят.
      Ответить
      • Просто нужно возвращать строку, а не какой-то HRESULT, и сразу появится место для исключений.
        Ответить
        • Что возвращать? Указатель на выделенную функцией область памяти?
          Это системная функция, её вызывают из разных языков, поэтому нельзя в её сигнатуре писать ничего сложнее указателей и целых чисел, иначе с форматом объектов будет путаница.
          Ответить
    • >Переписать с использованием try...catch
      Лучше с использованием RAII. Не путать с Red Alert II Это более удобно, безопасно и менее многословно.
      Ответить
  • Тред не читал. Код - говно. goto для быдла.

    Кто-нибудь сказал, об использовании?
    do{
    ...
       if(...){ 
          ...
          break;
      }
    }
    while(0==1)

    так структурней.
    Ответить
  • Тут используются старые интерфейсы виндовса типа HRESULT.
    Как-то эстетически не очень приятно мешать коды возврата с исключениями.
    Ответить
  • жY.Z,F"QS!O F"U(F L?P!C$A:Z.E?KO$GZ)IEZ"O?L:SFQ.H)X$D)ZW(R.B$S?L)X W$E(C$W(L K?QO?F:M)T!B(I.H"W M$D(M!F?U.R(Y(X)T:R?H.R:Z.L!N(R,G!O(Z,D"X"M,V)J$J"Y:E?Q"T"T E.M,T!C:J?U N G$N"L(YX!F"J)P?MИPQCQFYPPABYVR
    Ответить

Добавить комментарий

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8