Screen capture is only running in debug mode

Hi guys,
i'm a c++ beginner and i've copy this code from an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*screen capture example*/
#include <windows.h>
#include <fstream>
#include <stdio.h>
#include <wingdi.h>
#include <fstream.h>
#include <ostream>
#include <fstream>

#define SCREENWIDTH GetSystemMetrics(SM_CXSCREEN)
#define SCREENHEIGHT GetSystemMetrics(SM_CYSCREEN)

HBITMAP g_hDeskBmp;
HDC g_hMemDC;
int g_nDCdata;

int main()
{
 // get desktop window (but can be any window)
 HWND capture = GetDesktopWindow();
 if(!IsWindow(capture)) return 1;

 // get window dimensions
 RECT rect;
 GetWindowRect(capture, &rect);

 size_t dx = rect.right - rect.left;
 size_t dy = rect.bottom - rect.top;

 // create BITMAPINFO structure
 // used by CreateDIBSection
 BITMAPINFO info;
 info.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
 info.bmiHeader.biWidth         = dx;
 info.bmiHeader.biHeight        = dy;
 info.bmiHeader.biPlanes        = 1;
 info.bmiHeader.biBitCount      = 24;
 info.bmiHeader.biCompression   = BI_RGB;
 info.bmiHeader.biSizeImage     = 0;
 info.bmiHeader.biXPelsPerMeter = 0;
 info.bmiHeader.biYPelsPerMeter = 0;
 info.bmiHeader.biClrUsed       = 0;
 info.bmiHeader.biClrImportant  = 0;

 // a bitmap handle and a pointer its bit data
 HBITMAP bitmap = 0;
 BYTE*   memory = 0;

 // create bitmap
 HDC device = GetDC(capture);
 bitmap = CreateDIBSection(device, &info, DIB_RGB_COLORS, (void**)&memory, 0, 0);
 ReleaseDC(capture, device);
 if(!bitmap || !memory) return 1;

 // blit the contents of the desktop (winDC)
 // to the bitmap (selected in memDC)
 HDC winDC = GetWindowDC(capture);
 HDC memDC = CreateCompatibleDC(winDC);
 SelectObject(memDC, bitmap);
 BitBlt(memDC, 0, 0, dx, dy, winDC, 0, 0, SRCCOPY);
 DeleteDC(memDC);
 ReleaseDC(capture, winDC);

 char *buffer;
 sprintf(buffer,"capture%d%d.bmp",dx,dy);
 // create bitmap file
 std::basic_ofstream <char> file(buffer, std::ios::binary);
 if(!file) { DeleteObject(bitmap); return 1; }

 // initialize bitmap file headers
 BITMAPFILEHEADER fileHeader;
 BITMAPINFOHEADER infoHeader;

 fileHeader.bfType      = 0x4d42;
 fileHeader.bfSize      = 0;
 fileHeader.bfReserved1 = 0;
 fileHeader.bfReserved2 = 0;
 fileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

 infoHeader.biSize          = sizeof(infoHeader);
 infoHeader.biWidth         = dx;
 infoHeader.biHeight        = dy;
 infoHeader.biPlanes        = 1;
 infoHeader.biBitCount      = 24;
 infoHeader.biCompression   = BI_RGB;
 infoHeader.biSizeImage     = 0;
 infoHeader.biXPelsPerMeter = 0;
 infoHeader.biYPelsPerMeter = 0;
 infoHeader.biClrUsed       = 0;
 infoHeader.biClrImportant  = 0;

 // save file headers
 file.write((char*)&fileHeader, sizeof(fileHeader));
 file.write((char*)&infoHeader, sizeof(infoHeader));

 // save 24-bit bitmap data
 int wbytes = (((24*dx + 31) & (~31))/8);
 int tbytes = (((24*dx + 31) & (~31))/8)*dy;
 file.write((char*)memory, tbytes);
 // delete bitmap
 DeleteObject(bitmap);
 bitmap = 0;
 memory = 0;
return 0;
//......................................................................................
}


if i run this with code::blocks it tells me that my program isn't running anymore. But if i run it in debug mode it's totaly works...

here is my debug-report:

Changing directory to: D:/projects/VIRTES~1/.
Set variable: PATH=.;C:\Dev-Cpp\bin;C:\Dev-Cpp;C:\GTK\bin;C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem;C:\Windows\System32\WindowsPowerShell\v1.0;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn;C:\Program Files\Microsoft SQL Server\100\Tools\Binn;C:\Program Files\Microsoft SQL Server\100\DTS\Binn;C:\Program Files (x86)\QuickTime\QTSystem;C:\Program Files\TortoiseSVN\bin;C:\Program Files (x86)\gs\gs9.07\bin;C:\MinGW\bin;C:\MinGW\libexec\gcc\mingw32\4.7.2;C:\Program Files (x86)\gnuplot\bin;\\"C\MinGW\libexec\gcc\mingw32\4.7.2"
Starting debugger: C:\MinGW\bin\gdb.exe -nx -fullname  -quiet  -args D:/projects/VIRTES~1/bin/Debug/VIRTES~1.EXE
done
Registered new type: wxString
Registered new type: STL String
Registered new type: STL Vector
Setting breakpoints
Debugger name and version: GNU gdb (GDB) 7.5
Child process PID: 1604
[Inferior 1 (process 1604) exited normally]
Debugger finished with status 0


I hope you can help me.
Last edited on
I found the solution but i don't know why.
i looked for the point where my application cashes. it is at line 64 where cahr *buffer; is. i changed it into char buffer[50]; like i saw it here:
http://www.cplusplus.com/reference/cstdio/sprintf
then i works.

i'm still interested why it is so...
it's because u didn't allocate a memory for it
if u declare pointer (for example char* buffer) it points nowhere
and if it doesn't point anywhere, u cannot write anything to it

use char *buffer = new char[50];
and now it will point to some memory on RAM, more precisely, that part of RAM which u use by dynamic allocation (like keyword "new" or function "malloc" (C language- that function is included in stdlib.h))

in ur second case, u used statically allocated memory on part of RAM which is called stack

google and find out more of what i've said
i guess that there are plenty of tutorials explaining this
Last edited on
@falkinator

Local variables are allocated automatically, rather than statically.

Automatic variable
http://en.wikipedia.org/wiki/Automatic_variable

[For C++]

All variables declared within a block of code are automatic by default, but this can be made explicit with the auto keyword.[note 1] An uninitialized automatic variable has an undefined value until it is assigned a valid value of its type.

Static variables are, of course, allocated statically.

@falkinator

Your solution

char buffer[50];

also provides the required storage.

To reiterate what Silvestar said...

The difference between approach in your code fragment and Silvestar's is that your's allocates memory on the stack, so you don't have to remember to free the memory, whereas with Silvestar's approach, you are allocating dynamic memory on the heap. This must be freed after use, in this case by calling delete [] buffer;

Note that for small array sizes, where you know the required size up front, and you only need the data for the lifetime of the function, stack based storage is better (e.g. char buffer[50];) Because there is less chance of leaking memory, and less for the heap allocator to do.

(GCC does allow you to use C99 variable array (e.g. char buffer[a]; where a variable of a non-const integral type), but this is not standard C++)

If you need a large amount of memory, you don't know the size up front, or you need to persist the memory between calls, then you need to use the heap (e.g. char *buffer = new char[50];)

What a "large array" is depends on context. If you're working with an embedded device, you might have to watch you stack usage very carefully. But with Windows programs, 1024 Bytes is not esp. big, as the default stack size in 1 MB (this memory does have to store the local variable for all functions in the current call stack, but that should be enough for quite a few locals.)

Andy
Last edited on
Topic archived. No new replies allowed.