Crash allocating memory
| From: | Markus Duft | Date: | Mon, 25 Jul 2005 08:01:14 +0000 |
| Subject: | Crash allocating memory | ||
| Groups: | php.pecl.dev | ||
| Request: | Send a blank email to pecl-dev+get-2658@lists.php.net to get a copy of this message | ||
Hi!
I'm having a problem again... a somehow weird problem, and i can't figure it out.
I' have a method, which (using the windows api) alpha blends a bitmap on a device. Everything
works fine, and i don't think that there are any big mistakes in there. But the method only
works one or two times. After that it crashes while allocating memory (seems so). The really funny
thing is, that the function works ecellent while debugging. No crash, nothing. But when running the
final version from the command line, it crashes, whenever a paint event occurs (when the method is
called once more). when attaching a debugger at this point, it seems that the call stack is empty
and php is simply doing nothing, which seems pretty impossible to me. i can't do anything other
than terminate the program.
I'll post the method here, even though it's somehow a little long (sorry).
Regards, Markus!
P.S.: It seems like the one time it crashes at the first malloc (BITMAPINFO * bmi) and the other
time it crashes at the first free occuring (regardless which variable i'm freeing, i tried this
;o))
All the macros and so on work just fine. I'm pretty sure of that ;o) i use them in about 300
other methods without problems ;o)
ZEND_METHOD(xDevice, blendAlpha)
{
XDEVICE * pDevice;
XHANDLE * pBitmap, *pParent;
zval * zBitmap, *zParent = NULL;
int x, y;
HDC memDC;
BITMAPINFO *bmi = malloc(sizeof(BITMAPINFO));
void * pvBits = NULL;
BLENDFUNCTION bf;
BITMAP bmp;
int i, j;
HBITMAP tmpbm;
bool bDelete = true;
bool bUseIconAplpha = true;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|bO!", &zBitmap, &x,
&y, &bUseIconAplpha, &zParent, pce_xWindow) == FAILURE)
X_PARAMERROR;
if(Z_TYPE_P(zBitmap) != IS_OBJECT)
X_THROW("Only Objects are allowed as Parameter!");
X_GET_CONTEXT_SAVE(pDevice);
if(instanceof_function(Z_OBJCE_P(zBitmap), pce_xImage TSRMLS_CC))
{
zval * zType = dwl_read_prop(pce_xImage, zBitmap, "Type");
X_GET_HANDLE_SAVE_EX(pBitmap, pce_xObject, zBitmap);
memDC = CreateCompatibleDC(X_DEVCONTEXT_P(pDevice));
if(Z_LVAL_P(zType) != X_IMG_BITMAP)
{
ICONINFO ii;
GetIconInfo(X_HANDLE_P(pBitmap), &ii);
tmpbm = DuplicateBitmap(ii.hbmColor);
//need to preprocess all pixels here, to combine in the mask ;o)
if(!bUseIconAplpha)
{
void * iconBits, *maskBits;
int w, h;
//BITMAPINFO * tmpbmi = malloc(sizeof(BITMAPINFO));
BITMAPINFO * tmpbmi = bmi;
ZeroMemory(tmpbmi, sizeof(BITMAPINFO));
tmpbmi->bmiHeader.biSize = sizeof(BITMAPINFO);
if(!GetDIBits(memDC, tmpbm, 0, 0, NULL, tmpbmi, DIB_RGB_COLORS))
X_THROW("Unable to load Icon Information!");
if(tmpbmi->bmiHeader.biBitCount < 32) X_THROW("Only 32 Bit Icons are allowed!");
iconBits = malloc(tmpbmi->bmiHeader.biSizeImage);
maskBits = malloc(tmpbmi->bmiHeader.biSizeImage);
if(!GetDIBits(memDC, tmpbm, 0, tmpbmi->bmiHeader.biHeight, iconBits, tmpbmi, DIB_RGB_COLORS))
X_THROW("Cannot get Icon Pixel data!");
if(!GetDIBits(memDC, ii.hbmMask, 0, tmpbmi->bmiHeader.biHeight, maskBits, tmpbmi,
DIB_RGB_COLORS))
X_THROW("Cannot get Mask Pixel data!");
for(w = 0; w < tmpbmi->bmiHeader.biWidth; w++)
{
for(h = 0; h < tmpbmi->bmiHeader.biHeight; h++)
{
UCHAR alpha, red, green, blue;
alpha = ((UINT32*)maskBits)[w+h * tmpbmi->bmiHeader.biWidth];
red = GetBValue(((UINT32*)iconBits)[w+h * tmpbmi->bmiHeader.biWidth]);
green = GetGValue(((UINT32*)iconBits)[w+h * tmpbmi->bmiHeader.biWidth]);
blue = GetRValue(((UINT32*)iconBits)[w+h * tmpbmi->bmiHeader.biWidth]);
//Need to invert the mask Bitmap alpha values
if(alpha == 0xff) {
alpha = 0x00;
} else {
alpha = 0xff;
}
((UINT32*)iconBits)[w+h * tmpbmi->bmiHeader.biWidth] = (alpha << 24) | (red <<
16) | (green << 8) | (blue);
}
}
SetDIBits(memDC, tmpbm, 0, tmpbmi->bmiHeader.biHeight, iconBits, tmpbmi, DIB_RGB_COLORS);
free(iconBits);
free(maskBits);
}
} else {
tmpbm = DuplicateBitmap(X_HANDLE_P(pBitmap));
}
ZeroMemory(bmi, sizeof(BITMAPINFO));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if(!GetDIBits(memDC, tmpbm, 0, 0, NULL, bmi, DIB_RGB_COLORS))
X_THROW("Unable to retrieve Bitmap Information");
if(bmi->bmiHeader.biBitCount < 32)
X_THROW("Only 32 Bit Bitmaps can be used with blendChannel!");
pvBits = malloc(bmi->bmiHeader.biSizeImage);
if(!GetDIBits(memDC, tmpbm, 0, bmi->bmiHeader.biHeight, pvBits, bmi, DIB_RGB_COLORS))
X_THROW("Unable to retrieve Bitmap Bits!");
for(i = 0; i < bmi->bmiHeader.biWidth; i++)
{
for(j = 0; j < bmi->bmiHeader.biHeight; j++)
{
UCHAR uRed, uGreen, uBlue, uAlpha;
float fFactor;
uAlpha = ((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth] >> 24;
uRed = GetBValue(((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth]);
uGreen = GetGValue(((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth]);
uBlue = GetRValue(((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth]);
fFactor = (float)uAlpha / (float)0xff;
((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth] = (uAlpha << 24)
| ((UCHAR)(uRed * fFactor) << 16)
| ((UCHAR)(uGreen * fFactor) << 8)
| ((UCHAR)(uBlue * fFactor));
}
}
SetDIBits(memDC, tmpbm, 0, bmi->bmiHeader.biHeight, pvBits, bmi, DIB_RGB_COLORS);
SelectObject(memDC, tmpbm);
bmp.bmWidth = bmi->bmiHeader.biWidth;
bmp.bmHeight = bmi->bmiHeader.biHeight;
} else if(instanceof_function(Z_OBJCE_P(zBitmap), pce_xDevice TSRMLS_CC))
{
XDEVICE *pDev;
X_GET_CONTEXT_SAVE_EX(pDev, pce_xDevice, zBitmap);
memDC = X_DEVCONTEXT_P(pDev);
bDelete = false;
{
HBITMAP tmp;
tmp = DuplicateBitmap(SelectObject(memDC, CreateCompatibleBitmap(memDC, 0, 0)));
GetObject(tmp, sizeof(BITMAP), &bmp);
{
ZeroMemory(bmi, sizeof(BITMAPINFO));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if(!GetDIBits(memDC, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS))
X_THROW("Unable to retrieve Bitmap Information");
if(bmi->bmiHeader.biBitCount < 32)
X_THROW("Only 32 Bit Bitmaps can be used with blendChannel!");
pvBits = malloc(bmi->bmiHeader.biSizeImage);
if(!GetDIBits(memDC, tmp, 0, bmi->bmiHeader.biHeight, pvBits, bmi, DIB_RGB_COLORS))
X_THROW("Unable to retrieve Bitmap Bits!");
for(i = 0; i < bmi->bmiHeader.biWidth; i++)
{
for(j = 0; j < bmi->bmiHeader.biHeight; j++)
{
UCHAR uRed, uGreen, uBlue, uAlpha;
float fFactor;
uAlpha = ((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth] >> 24;
uRed = GetBValue(((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth]);
uGreen = GetGValue(((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth]);
uBlue = GetRValue(((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth]);
fFactor = (float)uAlpha / (float)0xff;
((UINT32*)pvBits)[i+j * bmi->bmiHeader.biWidth] = (uAlpha << 24)
| ((UCHAR)(uRed * fFactor) << 16)
| ((UCHAR)(uGreen * fFactor) << 8)
| ((UCHAR)(uBlue * fFactor));
}
}
SetDIBits(memDC, tmp, 0, bmi->bmiHeader.biHeight, pvBits, bmi, DIB_RGB_COLORS);
}
DeleteObject(SelectObject(memDC, tmp));
}
} else {
X_THROW("Invalid Object Type passed!");
}
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = AC_SRC_ALPHA;
bf.SourceConstantAlpha = 0xFF;
if(zParent)
{
XDWORD dwExStyle;
POINT pt_s;
SIZE sz;
X_GET_HANDLE_SAVE_EX(pParent, pce_xObject, zParent);
dwExStyle = xlib_window_get_ex_style(pParent);
if(!(dwExStyle & WS_EX_LAYERED))
X_THROW("Window has to be layered");
pt_s.x = 0;
pt_s.y = 0;
sz.cx = bmp.bmWidth;
sz.cy = bmp.bmHeight;
RETVAL_BOOL(UpdateLayeredWindow(X_HANDLE_P(pParent), GetDC(NULL), NULL, &sz, memDC, &pt_s,
0, &bf, ULW_ALPHA));
} else {
RETVAL_BOOL(AlphaBlend(
X_DEVCONTEXT_P(pDevice),
x,
y,
bmp.bmWidth,
bmp.bmHeight,
memDC,
0,
0,
bmp.bmWidth,
bmp.bmHeight,
bf));
}
if(bDelete)
DeleteDC(memDC);
free(bmi);
free(pvBits);
}