Ir ao conteúdo
  • Cadastre-se
DAVIFN

C++ - Falha em loop

Recommended Posts

Detalharei bem minha dúvida para que melhor seja respondida; o atual programa que estou desenvolvendo (que, por sinal, não possui fins comerciais, pois programo como um hobby), eventualmente, tira uma screenshot da tela de meu computador e a salva em um destino qualquer.

 

      O problema é que, após um tempo considerável de execução, o programa começa a apresentar algumas falhas que considero graves: As screenshots saem completamente pretas e o consumo de CPU aumenta significativamente.

 

      Pelo que até agora pesquisei, estou na pista de que, como não sou um profissional, devo ter deixado algum "leak" de memória em meu humilde código, coisa pouca, mas que, aos montes, causa os problemas acima citados. Achei um tópico no qual falavam que os tais "leaks" poderiam ser evitados usando uma série de if's (    if(talcoisa!=NULL)     ), e apliquei alguns if's ao meu código. Mesmo assim, continua problemático.

 

      Elaborei um mini-programa para postar neste tópico aqui, e, quando ele estiver funcionando, aplicarei-o em meu projeto. Ele basicamente tira mil screenshots e salva na pasta "teste". Ou pior, na teoria. Ele só está tirando umas duzentas screenshots (ao menos aqui). Ajudem-me a corrigi-lo e ficarei extremamente grato. Segue o código do programa de testes:

 

 

#include <windows.h>

#include <stdio.h>
 
 
//Tive de incluir isso para que compilasse no Dev-C++/////////////
#ifndef CAPTUREBLT
#define CAPTUREBLT (DWORD)0x40000000
//////////////////////////////////////////////////////////////////
 
#endif
//Código parcialmente tirado de um artigo. Adicionei apenas os if's
void es(char*BmpName)
{
HWND DesktopHwnd = GetDesktopWindow();
if(DesktopHwnd!=NULL)
{
RECT DesktopParams;
HDC DevC = GetDC(DesktopHwnd);
if(DevC!=NULL)
{
GetWindowRect(DesktopHwnd,&DesktopParams);
DWORD Width = DesktopParams.right - DesktopParams.left;
DWORD Height = DesktopParams.bottom - DesktopParams.top;
DWORD FileSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBTRIPLE)+1*(Width*Height*4));
    char *BmpFileData = (char*)GlobalAlloc(0x0040,FileSize);
PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
BFileHeader->bfType = 0x4D42;
BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
BInfoHeader->biPlanes = 1;
BInfoHeader->biBitCount = 24;
BInfoHeader->biCompression = BI_RGB;
BInfoHeader->biHeight = Height;
BInfoHeader->biWidth = Width;
RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
RGBTRIPLE color;
HDC CaptureDC = CreateCompatibleDC(DevC);
if(CaptureDC!=NULL)
{
HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC,Width,Height);
if(CaptureBitmap!=NULL)
{
SelectObject(CaptureDC,CaptureBitmap);
BitBlt(CaptureDC,0,0,Width,Height,DevC,0,0,SRCCOPY|CAPTUREBLT);
GetDIBits(CaptureDC,CaptureBitmap,0,Height,Image,(LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
DWORD Junk;
HANDLE FH = CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
if(FH!=NULL)
{
WriteFile(FH,BmpFileData,FileSize,&Junk,0);
CloseHandle(FH);
    
}GlobalFree(FH);}GlobalFree(BmpFileData);}}}
GlobalFree(BmpName);//Enchi de GlobalFree() também, não sei muito bem o que faz, mas, pelo que sei de inglês, libera a variável em questão
}
 
int main()
{
printf("Programa de teste.\n\nPressione alguma tecla para efetuar o teste... (tirar mil screenshots na pasta\n\"teste\")");
system("pause>nul");//Simples pausa
printf("\n\n\n\nScreenshots sendo armazenadas. Por favor, aguarde alguns instantes...");
CreateDirectory("teste",0);//Cria a pasta "teste", caso esta ainda não exista
char ca[256];
int qual=0;
while(qual!=1000)
{
qual++;
sprintf(ca,"teste\\%d.bmp",qual);//
es(ca);
}
MessageBox(NULL,"Mil screenshots foram armazenadas na pasta \"teste\" (ao menos na teoria)","Será?",MB_OK);
}

 

Obs: Meu objetivo é conseguir fazer com que o programa salve as mil screenshots.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Problema resolvido, pessoal! Não há mais necessidade de resposta e podem fechar o tópico, porém, não o deletem, assim caso mais alguém tenha a mesma dúvida que eu tive (algo meio difícil de acontecer) poderá solucioná-la. Segue o código contendo as linhas que alterei para que não houvessem mais "leaks":

 

 

#include <windows.h>

#include <stdio.h>
 
 
//Tive de incluir isso para que compilasse no Dev-C++/////////////
#ifndef CAPTUREBLT
#define CAPTUREBLT (DWORD)0x40000000
//////////////////////////////////////////////////////////////////
 
#endif
//Código parcialmente tirado de um artigo. Adicionei apenas os if's
void es(char*BmpName)
{
HWND DesktopHwnd = GetDesktopWindow();
if(DesktopHwnd!=NULL)
{
RECT DesktopParams;
HDC DevC = GetDC(DesktopHwnd);
if(DevC!=NULL)
{
GetWindowRect(DesktopHwnd,&DesktopParams);
DWORD Width = DesktopParams.right - DesktopParams.left;
DWORD Height = DesktopParams.bottom - DesktopParams.top;
DWORD FileSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBTRIPLE)+1*(Width*Height*4));
    char *BmpFileData = (char*)GlobalAlloc(0x0040,FileSize);
PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];
BFileHeader->bfType = 0x4D42;
BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
BInfoHeader->biPlanes = 1;
BInfoHeader->biBitCount = 24;
BInfoHeader->biCompression = BI_RGB;
BInfoHeader->biHeight = Height;
BInfoHeader->biWidth = Width;
RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
RGBTRIPLE color;
HDC CaptureDC = CreateCompatibleDC(DevC);
if(CaptureDC!=NULL)
{
HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC,Width,Height);
if(CaptureBitmap!=NULL)
{
SelectObject(CaptureDC,CaptureBitmap);
BitBlt(CaptureDC,0,0,Width,Height,DevC,0,0,SRCCOPY|CAPTUREBLT);
GetDIBits(CaptureDC,CaptureBitmap,0,Height,Image,(LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);
DWORD Junk;
HANDLE FH = 
CreateFileA(BmpName,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
DeleteObject(CaptureDC);//adicionei isso primeiramente, e percebi um aumento das screenshots
DeleteObject(CaptureBitmap);//ao adicionar mais isso, aparentemente eliminei os leaks causados pela "não-deletação" dos bitmaps e hdcs, pois as mil screenshots foram tiradas com sucesso
if(FH!=NULL)
{
WriteFile(FH,BmpFileData,FileSize,&Junk,0);
CloseHandle(FH);
    
}GlobalFree(FH);}GlobalFree(BmpFileData);}}}
GlobalFree(BmpName);//Enchi de GlobalFree() também, não sei muito bem o que faz, mas, pelo que sei de inglês, libera a variável em questão
}
 
int main()
{
printf("Programa de teste.\n\nPressione alguma tecla para efetuar o teste... (tirar mil screenshots na pasta\n\"teste\")");
system("pause>nul");//Simples pausa
printf("\n\n\n\nScreenshots sendo armazenadas. Por favor, aguarde alguns instantes...");
CreateDirectory("teste",0);//Cria a pasta "teste", caso esta ainda não exista
char ca[256];
int qual=0;
while(qual!=1000)
{
qual++;
sprintf(ca,"teste\\%d.bmp",qual);//
es(ca);
}
MessageBox(NULL,"Mil screenshots foram armazenadas na pasta \"teste\" (ao menos na teoria)","Será?",MB_OK);
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×