• Sign in
 

LATAM Team blog

Search Blogs
Tags
  • Cloud
  • Cluster
  • Crash
  • Desarrollo
  • Desenvolvimento
  • Directory Services
  • DST
  • Español
  • Exchange/Outlook
  • Hang
  • High Availability
  • IIS
  • Networking
  • Office
  • People
  • Performance
  • Português
  • PowerShell Scripts
  • Security
  • Setup
  • Sharepoint
  • SQL
  • Virtualization
  • Windbg Scripts
  • Windows
Blog - News

Where Are You Coming From Today?

Where are you now?

Follow us on:

Options
  • Blog Home
  • About
  • Share this
  • RSS for posts
  • Atom
  • RSS for comments
Archive
Archives
  • June 2013 (5)
  • May 2013 (5)
  • April 2013 (5)
  • March 2013 (6)
  • February 2013 (3)
  • January 2013 (3)
  • December 2012 (2)
  • November 2012 (1)
  • October 2012 (4)
  • September 2012 (5)
  • August 2012 (2)
  • July 2012 (2)
  • June 2012 (3)
  • May 2012 (13)
  • April 2012 (6)
  • March 2012 (6)
  • February 2012 (4)
  • January 2012 (7)
  • December 2011 (11)
  • October 2011 (6)
  • September 2011 (1)
  • August 2011 (3)
  • July 2011 (7)
  • June 2011 (6)
  • May 2011 (5)
  • April 2011 (2)
  • March 2011 (13)
  • February 2011 (1)
  • January 2011 (5)
  • December 2010 (6)
  • November 2010 (1)
  • October 2010 (6)
  • September 2010 (2)
  • August 2010 (3)
  • July 2010 (3)
  • June 2010 (5)
  • May 2010 (1)
  • April 2010 (10)
  • March 2010 (21)
  • February 2010 (8)
  • January 2010 (3)
  • December 2009 (5)
  • November 2009 (5)
  • October 2009 (6)
  • September 2009 (8)
  • August 2009 (9)
  • July 2009 (1)
  • June 2009 (3)
  • May 2009 (2)
  • April 2009 (7)
  • March 2009 (4)
  • February 2009 (7)
  • January 2009 (7)
  • December 2008 (8)
  • November 2008 (7)
  • October 2008 (22)
  • September 2008 (17)
  • August 2008 (13)
  • July 2008 (11)
  • June 2008 (7)
  • May 2008 (3)
  • April 2008 (2)
  • March 2008 (6)
  • January 2008 (4)
  • December 2007 (9)
  • November 2007 (4)
  • October 2007 (3)
  • September 2007 (8)
  • August 2007 (4)
  • July 2007 (2)
  • June 2007 (5)
  • May 2007 (7)
  • April 2007 (9)
  • March 2007 (7)
  • February 2007 (6)
  • January 2007 (4)
  • December 2006 (14)
  • November 2006 (10)
  • October 2006 (10)
  • September 2006 (11)
  • August 2006 (15)
  • July 2006 (7)
  • June 2006 (14)
  • May 2006 (22)
  • April 2006 (16)
  • March 2006 (20)
  • January 2006 (1)

Resposta ao Desafio da Semana #10 [Hang/Crash com Loops em C# e VB.NET]

TechNet Blogs > LATAM Team blog > Resposta ao Desafio da Semana #10 [Hang/Crash com Loops em C# e VB.NET]

Resposta ao Desafio da Semana #10 [Hang/Crash com Loops em C# e VB.NET]

LatamBlog
8 Sep 2006 8:56 PM
  • Comments 1

 

Por: Roberto Alexis Farah

 

Olá pessoal!

Eis a resposta ao desafio http://blogs.technet.com/latam/archive/2006/08/25/451782.aspx publicado semana passada.

 

 

SINTOMA

 

A execução do código vai ocasionar um crash de aplicação devido a estouro de pilha (StackOverflow).

Se você pensou em loop infinito infelizmente errou pois o loop será transitório até que a pilha estoure.

 

 

PROBLEMA

 

O código faz uma chamada a DoSomething() recursivamente, o que ocasiona o estouro de pilha (stack overflow).

 

 

SOLUÇÃO

 

Uma solução simples, que exige poucas mudanças seria…

Ao invés de:

 

          public void DoSomething()

              {

                   DoSomething();

                   _b1 = _a1;

              }

 

Use:

 

          public class B : A

          {

              public int _b1;

             

              public void DoSomething()

              {

                   base.DoSomething();    // Chamada a classe pai.

                   _b1 = _a1;

              }

          }

 

 

Desse modo o método “pai” é chamado do método “filho”, como indicado no comentário.

Agora, eis a demonstração do que ocorre ao se executar o código acima… Vamos aos porques…

 

Sempre que uma rotina é chamada é colocada na pilha de execução algumas informações relacionadas a chamada do método que após a execução são removidas.

Entretanto, em uma chamada recursiva a remoção do conteúdo da pilha ocorrerá apenas quando a recursão terminar!

No nosso cenário a recursão nunca vai acabar portanto, a pilha vai encher e ocorrerá uma exceção quando o limite for atingido.

 

Eis uma amostra da pilha, pois o número de frames é muito maior que isso:

 

 

OS Thread Id: 0xe8c (0)

ESP       EIP    

00033000 00ca0134 Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033008 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033010 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033018 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033020 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033028 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033030 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033038 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033040 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033048 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033050 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033058 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033060 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033068 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033070 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033078 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033080 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033088 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033090 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

00033098 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330a0 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330a8 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330b0 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330b8 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330c0 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330c8 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330d0 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330d8 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

000330e0 00ca013a Test.Program+B.DoSomething()

    PARAMETERS:

        this = 0x01271be0

 

 

Notem como ESP constantemente muda para refletir o incremento na pilha.

O endereço vai do maior número (endereço de memória virtual) para o menor, que é como a pilha cresce.

 

A pilha, por default, tem aproximadamente 1 mb de tamanho para cada thread, logo, ao se tentar passar esse limite ocorre a exceção.

Para nossa thread em questão temos:

 

TEB at 7ffdf000

    ExceptionList:        0012f4ac

    StackBase:            00130000           

    StackLimit:           00031000

    SubSystemTib:         00000000

    FiberData:            00001e00

    ArbitraryUserPointer: 00000000

    Self:                 7ffdf000

    EnvironmentPointer:   00000000

    ClientId:             000013e8 . 00000e8c

    RpcHandle:            00000000

    Tls Storage:          00000000

    PEB Address:          7ffd8000

    LastErrorValue:       2

    LastStatusValue:      c000000f

    Count Owned Locks:    0

    HardErrorsMode:       0

 

 

A diferença da base e limite é: 0n1044480 (decimal) ou  0x000ff000 (hexadecimal)

É possível ver que o limite foi atingido. De fato, temos a exceção:

 

ExceptionAddress: 00ca0134 (Test!Test.Program+B.DoSomething()+0x00000014)

   ExceptionCode: c00000fd (Stack overflow)

  ExceptionFlags: 00000000

NumberParameters: 2

   Parameter[0]: 00000001

   Parameter[1]: 00032ffc

 

 

 

E a parte do código que ocasionou a exceção:

 

Test!Test.Program+B.DoSomething()+14 [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00ca0134 ff1568319100    call    dword ptr ds:[913168h]

 

    23:                              public int _b1;

    24:                             

    25:                              public void DoSomething()

    26:                              {

>  27:                                       DoSomething();

    28:                                       _b1 = _a1;

    29:                              }

    30:                    }

    31:                   

    32:                    static void Main(string[] args)

 

 

Eis as últimas chamadas na pilha até o momento do overflow. Aqui fica bem claro o preenchimento da pilha através das chamadas recursivas e finalizando em 00033000:

 

00032ff4  00000000

00032ff8  00000000

00032ffc  00000000

00033000  01271be0

00033004  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033008  01271be0

0003300c  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033010  01271be0

00033014  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033018  01271be0

0003301c  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033020  01271be0

00033024  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033028  01271be0

0003302c  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033030  01271be0

00033034  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033038  01271be0

0003303c  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033040  01271be0

00033044  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033048  01271be0

0003304c  00ca013a Test!Test.Program+B.DoSomething()+0x1a [C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\Program.cs @ 27]

00033050  01271be0

 

 

O que é o endereço 01271be0 que aparece acima?

 

Name: Test.Program+B

MethodTable: 00913130

EEClass: 00911364

Size: 20(0x14) bytes

GC Generation: 0

 (C:\Development\My Tools\BLOG Articles\Article #15\Test\Test\bin\Debug\Test.exe)

Fields:

      MT    Field   Offset                 Type VT     Attr    Value Name

790fed1c  4000001        4         System.Int32  0 instance        0 _a1

790fed1c  4000002        8         System.Int32  0 instance        0 _b1

790fed1c  4000003        c         System.Int32  0 instance        0 _b1

 

 

Portanto, a cada nova chamada do método informações são colocadas na pilha e nunca removidas. Após várias execuções, quando a pilha atinge seu limite de ~1mb temos a exceção por estouro de pilha!

 

Para aqueles que estiverem se perguntando quando temos um sintoma de loop infinito, eis um exemplo:

 

while(1)

{

        Console.WriteLine("X");    // Loop infinito sempre é acompanhado de alto consumo de CPU???

}

 

 

Por que nesse caso temos um loop infinito (com alto consumo de CPU) ao invés de um estouro de pilha?

 

A resposta é simples, nesse caso as informações colocadas na pilha quando a rotina dentro do loop é chamada são removidas quando a execução retorna para o loop, ou seja, o espaço necessário na pilha para permitir a chamada desse método é muito pequeno pois é constantemente limpa quando a execução de Console.WriteLine() finaliza. Não há uma serialização de chamadas na pilha que nunca são retornadas como no caso do desafio colocado.

 

Agora atente para um detalhe importante: No loop acima temos um cenário de alto consumo de CPU não por ser um loop infinito, mas por ser um loop sem uma pausa para o processador “respirar”, digo, sem por exemplo, uma chamada para Sleep(200). O que quero dizer com isso é que podem haver cenários de loops infinitos de alta CPU ou loops infinitos de baixa CPU, tudo depende de haver chamadas dentro do loop que possibilitem a CPU dedicar mais tempo de processamento para as outras threads ou não.

 

Acredito que após entender esse desafio você estará apto a examinar um código suspeito e identificar se é candidato a crash por stack overflow ou um loop infinito (hang, aplicação pendurada), e se poderia haver um consumo elevado de CPU ou não. J

 

Como havia dito ao postar o desafio, algumas semanas atrás usei-o em entrevistas e curiosamente ninguém acertou 100%.

O loop infinito foi a resposta mais usada.

 

Até o próximo desafio.

  • 1 Comments
Desenvolvimento , Performance, Hang, Crash
Comments
Comments
  • Alexandre Albuquerque
    8 Sep 2006 10:04 PM
    Parabéns mais uma vez Roberto. Os tópicos são bem feitos e não somente com teoria, mas exemplificando na prática (amostras das pilhas, etc).

    Creio que o crescimento técnico do pessoal que acompanha o blog tenha crescido bastante! Principalmente aos que se sentem desafiados e correm para tentar matar a charada. Já dizia o ditado "O que vem fácil, sai fácil!"... Valew! =P Inté o próximo!
Page 1 of 1 (1 items)
  • © 2013 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy & Cookies
  • 5.6.426.415
  • TechNet
  • Products
  • IT Resources
  • Downloads
  • Training
  • Support
Products
  • Windows
  • Windows
    Server
  • System
    Center
  • Internet
    Explorer
 
  • Office
  • Office 365
  • Exchange
    Server
 
  • SQL Server
  • SharePoint
    Products
  • Lync
  • See all products »
Resources
  • Evaluation Center
  • Learning Resources
  • Microsoft IT Camps
  • Microsoft Technical Communities
  • Microsoft Virtual Academy
  • Script Center
  • Server and Tools Blogs
  • Solution Accelerators
  • TechNet Blogs
 
  • TechNet Flash Newsletter
  • TechNet Gallery
  • TechNet Library
  • TechNet Magazine
  • TechNet Subscriptions
  • TechNet Video
  • TechNet Wiki
  • Windows Sysinternals
  • Virtual Labs
Solutions
  • Networking
  • Cloud and Datacenter
  • Security
  • Virtualization
Updates
  • Service Packs
  • Security Bulletins
  • Microsoft Update
Trials
  • Windows Server 2012
  • System Center 2012
  • Microsoft SQL Server 2012 SP1
  • Windows 8 Enterprise
  • See all trials »
Related Sites
  • Microsoft Download Center
  • TechNet Evaluation Center
  • Drivers
  • Compatability & Converters
  • Windows Sysinternals
  • TechNet Gallery
Training
  • Training Catalog
  • Class Locator
  • Microsoft Virtual Academy
  • Free Windows Server 2012 courses
  • Free Windows 8 courses
  • SQL Server training
  • e-Learning overview
Certifications
  • Certification overview
  • MCSA: Windows 8
  • Windows Server Certification (MCSE)
  • Private Cloud Certification (MCSE)
  • SQL Server Certification (MCSE)
Other resources
  • TechNet Events
  • Second shot for certification
  • Born To Learn blog
  • IT Camps
Support by product
  • Exchange Server
  • Forefront Server
  • Forefront Edge Security
  • Forefront Server Security
  • Internet Explorer
  • Office
  • SharePoint
 
  • SQL Server
  • System Center
  • Windows Server
  • Windows XP
  • Windows Vista
  • Windows 7
  • Windows 8
Other support links
  • Microsoft Premier Online
  • Microsoft Fix It Center
  • TechNet Forums
  • MSDN Forums
  • Security Bulletins & Advisories
  • International support solutions
  • Log a support ticket
  • Look up event IDs and error codes
Not an IT pro?
  • Microsoft Customer Support
  • Microsoft Community Forums