logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog


C++ com sanidade: fazendo a IDE do Visual Studio.NET trabalhar para você

Uma das coisas mais irritantes que acontecem durante o DEBUG de uma aplicação ATL, é o fato do VS.NET insistir em fazer debug das sobrecargas de operadores dos "SmartTypes" do ATL. Quando você usa "Step Into" (F11) para fazer debug de uma função, você é obrigado a passar por todas as sobrecargas de operadores antes de chegar na função. Como um pedaço de código fonte vale mais do que (e*pi)^3 palavras, vamos ao que interessa:

HRESULT DoTheFlufflers(BSTR str, VARIANT v, IUnknown* pUnk)
{
   MessageBox(NULL, str, L"BSTR", MB_OK);

   if(v.vt == VT_BSTR)
      MessageBox(NULL, v.bstrVal, L"VARIANT", MB_OK);
   else
   {
      MessageBox(NULL, 
                 L"Será que você poderia, por obséqio, colocar uma string nessa Variant?", 
                 L"VARIANT", 
                 MB_OK);
      return E_UNEXPECTED;
   }

   //
   // dã!
   //
   pUnk->AddRef();
   
   pUnk->Release();

   return S_OK;
}

int main()
{
   HRESULT hr;
   CComBSTR str;
   CComVariant v;
   CComPtr pUnk;

   str = L"Eu sou uma string legal, podemos ser amigos?";
   v = 0xDEADBEEF;

   hr = CoCreateInstance(CLSID_FLUFFLERS, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pUnk);

   if(FAILED(hr))
   {
      OutputDebugString(L"Eu desisto...");
      //
      // pena que não funciona em UserMode...
      //
      // KeBugCheckEx(0xFFFFFFFF,0,0,0,0);
      return hr;
   }

   DoTheFlufflers(str, v, pUnk);  // <<-- Muito chato fazer Step Into nessa função...

   return 0;

}

Quando você usar o F11 sobre a instrução "DoTheFlufflers(str, v, pUnk);", o VS.NET vai entrar primeiro em "ComPtrBase::operator T*()", depois em "CComBSTR::operator BSTR()", e só depois em "DoTheFlufflers". Se essa função fosse de um objeto COM (algo como "pUnk->DoTheFlufferization(str, v, pUnk)"), você ainda teria chamada de "ComPtrBase::operator ->" antes das outras. Isso realmente é muito chato.

Mas há uma solução para esse problema no VS.NET: Existe a chave [HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio7.1\\NativeDE\\StepOver], onde você pode colocar nomes de funções que não terão StepInto. É só criar valores string com um id numérico e com valor "um_regular_expression=NoStepInto". Para ignorar todos os métodos de CComPtr, use algo como ".+CComPtr.+=NoStepInto". A minha configuração por enquanto é essa:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio7.1\\NativeDE\\StepOver]
"100"=".+CCom.*Ptr.+=NoStepInto"
"99"=".+CComBSTR.+=NoStepInfo"
"98"=".+CComVariant.+=NoStepInfo"
"97"=".+CAtlMap.*=NoStepInfo"
"96"=".+CAutoPtr.+=NoStepInto"

Os valores são avaliados em ordem inversa. Essa configuração pode ser modificada sem reiniciar o VS.NET, parece que ela é recarregada a cada sessão de debug. Para maiores informações sobre esse assunto, dê uma olhada nessa mensagem de alguém da equipe do C#, que mandou um CTRL+C, CTRL+V da única documentação que existe sobre esse recurso: o código fonte da IDE do Visual Studio.NET.


Em 31/03/2005 04:56, por Rodrigo Strauss


  
 
 
Comentários
Alfred Gary Myers Jr. | website | em 31/03/2005 | #
A FCL tem alguns recursos interessantes para este cenário em managed code.
Dentro de System.Diagnostics existem diversos atributos que controlam o fluxo de depuração como, pro exemplo, DebuggerHiddenAttribute e DebuggerStepThroughAttribute.

Outra coisa... Os últimos samples estão bem mais legíveis para os não-iniciados. Muito bom!

Existe algum lugar em que se explique a correlação e diferenças entre Win32, COM, ATL, WTL, MFC e outras APIs e/ou frameworks? Fica a sugestão de escrever sobre isto.
Rodrigo Strauss | website | em 31/03/2005 | #
Eu já tinha visto algo sobre isso em .NET, algumas classes geradas pelo VS.NET (DataSet Tipado??) usam esses atributos para evitar esses aborrecimentos que eu falei. Esses dois enfoques tem vantagens e desvantagens. Pelo menos o enfoque .NET é documentado... :-)

Quanto à legibilidade, eu tenho me esforçado para isso, justamente para mostrar que C++ não é coisa do outro mundo.

Nunca vi nada sobre as diferenças entre as sopas de letrinhas. É realmente uma boa sugestão.
Rodrigo Strauss | website | em 31/03/2005 | #
Achei algo que ajuda a explicar a sopa de letrinhas (apesar de não ser esse o objetivo do artigo):

http://www.msversus.org/title/What's+The+Need+For+.NET%3F
Nonaka | em 30/04/2015 | #
Nossa se eu soubesse isso antes :)!
rebarba rebarba
  ::::