Click here to Skip to main content
16,017,852 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have a program that compiles and runs with the exception of a couple of pop-up menu items that are dependent on an image (bitmap, specifically) being initialized. I can find the part of the code that generates the error message, but since there are no syntax errors I am not quite sure why this isn't working. If anyone thinks they might be able to help I can post some parts of the code....if not, a good tip on how to identify what classes and functions are dependent on each other so that I can trace what the code is doing would be great help. I am using VS2010.

Here is the code from one of the entries in the pop-up menu that leads to the bitmap problem:

void CWinSTMView::OnImageLinDcOffset()
{
    CWinSTMDoc *pDoc = CreateNewDoc(GetDocument());
    strcat(pDoc->m_ChanHead[0]->AppliedFilters,"Linear DC Offset. ");

    int ave;
    //linear DC subtract
    for(int i=0;i< m_NScans;i++)
        {
            ave = 0;
            for(int j=0;j< m_NPts;j++)
            {
                ave += pDoc->m_Chan[0]->ipData[j+i*m_NPts];
            }
            ave /= m_NPts;

            for(int j = 0;j< m_NPts;j++)
                {
                    pDoc->m_Chan[0]->ipData[j+i*m_NPts] -= ave;
                }
        }
    m_Change = 1;
    Invalidate(true);

}


The above code does not execute, it leads to the following code execution: AfxMessageBox("Bitmap has not been init"); from I think this part of the program:

#include "stdafx.h"
#include "winstmbmp.h"

CWinSTMBmp::CWinSTMBmp(void)
{
    ZeroMemory(&m_HistogramData,sizeof(int)*256);
    m_ImageMode     = IMAGE_MODE_HORIZONTAL;
    m_Inversion     = false;
    m_Derivative    = false;
    m_LineDC        = false;
    m_Render        = false;
    m_Bitmap        = NULL;
    m_BmpBits       = NULL;
    m_SizeX         = 0;
    m_SizeY         = 0;

}

CWinSTMBmp::~CWinSTMBmp(void)
{
    if(m_Bitmap != NULL)
        DeleteObject(m_Bitmap);
}

bool CWinSTMBmp::Init(int sizex, int sizey, RGBQUAD* Pal)
{
    // if bmp already exists, delete it and start over
    if (m_Bitmap != NULL)
        DeleteObject(m_Bitmap);

    // create Bitmap in memory
    if (m_Bitmap == NULL)
    {
        ZeroMemory ( &m_ImageInfo, sizeof (BITMAPINFO) );
        m_ImageInfo.bmiHeader.biSize        = sizeof (BITMAPINFOHEADER);
        m_ImageInfo.bmiHeader.biWidth       = sizex;
        m_ImageInfo.bmiHeader.biHeight      = -sizey;
        m_ImageInfo.bmiHeader.biPlanes      = 1;
        m_ImageInfo.bmiHeader.biBitCount    = 32;
        m_ImageInfo.bmiHeader.biCompression = BI_RGB;
        m_ImageInfo.bmiHeader.biSizeImage   = 0;

        m_Bitmap=CreateDIBSection ( NULL, &m_ImageInfo, DIB_RGB_COLORS, (void **)&m_BmpBits, NULL, NULL );
    }

    // copy pallet
    memcpy(m_RGB,Pal,sizeof(RGBQUAD)*256);

    m_SizeX = sizex;
    m_SizeY = sizey;

    return true;
}

HBITMAP CWinSTMBmp::GetHBitmap(void)
{
    return HBITMAP(m_Bitmap);
}

BITMAPINFO* CWinSTMBmp::GetBmpInfo(void)
{
    return &m_ImageInfo;
}

bool CWinSTMBmp::Render(int* Data,int Min, int Max)
{
    if(Data == NULL)
    {
        AfxMessageBox("Passing in a NULL Data Ptr");
        return false;
    }

    if(m_Bitmap == NULL)
    {
        AfxMessageBox("Bitmap has not been init");
        return false;
    }

    // Only the Render Function sets these
    m_Min = Min;
    m_Max = Max;

    //clear Histogram data
    ZeroMemory(m_HistogramData,sizeof(int)*256);

    int temp; // color index

    // Keep range, but remove DC component
    if(m_LineDC)
    {
        double LRange = (Max + Min)/2;
        Max -= LRange;
        Min -= LRange;
    }

    //calculate Color Scale factor
    double ColorScale = 256.0 / (Max - Min);

    int SlowScanInc, FastScanInc,SlowMax,FastMax;

    if(m_ImageMode == IMAGE_MODE_HORIZONTAL)
    {
        SlowScanInc = m_SizeX;
        FastScanInc = 1;
        SlowMax     = m_SizeY;
        FastMax     = m_SizeX;
    }
    else // vertical
    {
        SlowScanInc = 1;
        FastScanInc = m_SizeX;
        SlowMax     = m_SizeX;
        FastMax     = m_SizeY;
    }


    for(int K = 0; K < SlowMax; K++)
    {
        int slow = K * SlowScanInc;

        double Ave = 0.0;

        if(m_LineDC)
        {
            for(int J = 0; J < FastMax; J++)
            {
                int fast = J * FastScanInc;
                int index = slow+fast;
                if(!m_Derivative)
                    Ave += Data[index];
                if(m_Derivative && J != 0)
                    Ave += Data[index - FastScanInc] - Data[index];

            }

            if(m_ImageMode == IMAGE_MODE_HORIZONTAL)
                Ave /= m_SizeX;
            else
                Ave /= m_SizeY;
        }//End if m_LinDC


        for(int J = 0; J < FastMax; J++)
        {
            int temp=0;
            int fast = J * FastScanInc;
            int index = slow+fast;

            if(!m_Derivative) // if topo/image mode
            {
                temp = round((Data[index] - Min - Ave) * ColorScale);
            }

            if(m_Derivative && J != 0)  //if Deriv
            {
                temp = round((Data[index - FastScanInc] - Data[index] - Min - Ave) * ColorScale);
            }


            temp = min(temp,255);
            temp = max(temp,0);
            m_HistogramData[temp]++;

            if(!m_Inversion)
            {
                m_BmpBits[index] = m_RGB[255-temp];
            }
            else
            {
                m_BmpBits[index] = m_RGB[temp];
            }

        }// end for
    } // end for

    return true;
}

RGBQUAD* CWinSTMBmp::GetBmpBits(void)
{
    return m_BmpBits;
}

void CWinSTMBmp::SetLineDC(bool enable)
{
    m_LineDC = enable;
}

void CWinSTMBmp::SetInversion(bool enable)
{
    m_Inversion = enable;
}

void CWinSTMBmp::SetDer(bool enable)
{
    m_Derivative = enable;
}

void CWinSTMBmp::UpdatePallet(RGBQUAD* Pal)
{
    // copy pallet
    memcpy(m_RGB,Pal,sizeof(RGBQUAD)*256);
}

int* CWinSTMBmp::GetHistogramData(void)
{
    return m_HistogramData;
}

// Sets all rendering parameters
void CWinSTMBmp::SetProperties(bool Derivative, bool LineDC, int Direction, bool Invert)
{
    m_Inversion = Invert;
    m_Derivative = Derivative;
    m_LineDC    = LineDC;
    m_ImageMode = Direction;
}

void CWinSTMBmp::DeleteBmp(void)
{
    if(m_Bitmap != NULL)
        DeleteObject(m_Bitmap);

    ZeroMemory(&m_HistogramData,sizeof(int)*256);
    m_ImageMode     = IMAGE_MODE_HORIZONTAL;
    m_Inversion     = false;
    m_Derivative    = false;
    m_LineDC        = false;
    m_Render        = false;
    m_Bitmap        = NULL;
    m_BmpBits       = NULL;
    m_SizeX         = 0;
    m_SizeY         = 0;

}


// render an unsigned short array
bool CWinSTMBmp::RenderUI(unsigned short* Data, int Min, int Max)
{
    if(Data == NULL)
    {
        AfxMessageBox("Passing in a NULL Data Ptr");
        return false;
    }

    if(m_Bitmap == NULL)
    {
        AfxMessageBox("Bitmap has not been init");
        return false;
    }

    // Only the Render Function sets these
    m_Min = Min;
    m_Max = Max;

    //clear Histogram data
    ZeroMemory(m_HistogramData,sizeof(int)*256);

    int temp; // color index

    // Keep range, but remove DC component
    if(m_LineDC)
    {
        double LRange = (Max + Min)/2;
        Max -= LRange;
        Min -= LRange;
    }

    //calculate Color Scale factor
    double ColorScale = 256.0 / (Max - Min);

    int SlowScanInc, FastScanInc,SlowMax,FastMax;

    if(m_ImageMode == IMAGE_MODE_HORIZONTAL)
    {
        SlowScanInc = m_SizeX;
        FastScanInc = 1;
        SlowMax     = m_SizeY;
        FastMax     = m_SizeX;
    }
    else // vertical
    {
        SlowScanInc = 1;
        FastScanInc = m_SizeX;
        SlowMax     = m_SizeX;
        FastMax     = m_SizeY;
    }


    for(int K = 0; K < SlowMax; K++)
    {
        int slow = K * SlowScanInc;

        double Ave = 0.0;

        if(m_LineDC)
        {
            for(int J = 0; J < FastMax; J++)
            {
                int fast = J * FastScanInc;
                int index = slow+fast;
                if(!m_Derivative)
                    Ave += Data[index];
                if(m_Derivative && J != 0)
                    Ave += Data[index - FastScanInc] - Data[index];

            }

            if(m_ImageMode == IMAGE_MODE_HORIZONTAL)
                Ave /= m_SizeX;
            else
                Ave /= m_SizeY;
        }//End if m_LinDC


        for(int J = 0; J < FastMax; J++)
        {
            int temp=0;
            int fast = J * FastScanInc;
            int index = slow+fast;

            if(!m_Derivative) // if topo/image mode
            {
                temp = round((Data[index] - Min - Ave) * ColorScale);
            }

            if(m_Derivative && J != 0)  //if Deriv
            {
                temp = round((Data[index - FastScanInc] - Data[index] - Min - Ave) * ColorScale);
            }


            temp = min(temp,255);
            temp = max(temp,0);
            m_HistogramData[temp]++;

            if(!m_Inversion)
            {
                m_BmpBits[index] = m_RGB[255-temp];
            }
            else
            {
                m_BmpBits[index] = m_RGB[temp];
            }

        }// end for
    } // end for

    return true;
}

bool CWinSTMBmp::RenderMetaBmp(int * Data, int Min, int Max)
{
    if(Data == NULL)
    {
        AfxMessageBox("Passing in a NULL Data Ptr");
        return false;
    }

    if(m_Bitmap == NULL)
    {
        AfxMessageBox("Bitmap has not been init");
        return false;
    }

    if(Min == 0 && Max == 0)
    {
        Min = m_Min;
        Max = m_Max;
    }

    //clear Histogram data
    ZeroMemory(m_HistogramData,sizeof(int)*256);

    int temp; // color index

    // Keep range, but remove DC component
    if(m_LineDC)
    {
        double LRange = (Max + Min)/2;
        Max -= LRange;
        Min -= LRange;
    }

    //calculate Color Scale factor
    double ColorScale = 256.0 / (Max - Min);

    int SlowScanInc, FastScanInc,SlowMax,FastMax;

    if(m_ImageMode == IMAGE_MODE_HORIZONTAL)
    {
        SlowScanInc = m_SizeX;
        FastScanInc = 1;
        SlowMax     = m_SizeY;
        FastMax     = m_SizeX;
    }
    else // vertical
    {
        SlowScanInc = 1;
        FastScanInc = m_SizeX;
        SlowMax     = m_SizeX;
        FastMax     = m_SizeY;
    }


    for(int K = 0; K < SlowMax; K++)
    {
        int slow = K * SlowScanInc;

        double Ave = 0.0;

        if(m_LineDC)
        {
            for(int J = 0; J < FastMax; J++)
            {
                int fast = J * FastScanInc;
                int index = slow+fast;
                if(!m_Derivative)
                    Ave += Data[index];
                if(m_Derivative && J != 0)
                    Ave += Data[index - FastScanInc] - Data[index];

            }

            if(m_ImageMode == IMAGE_MODE_HORIZONTAL)
                Ave /= m_SizeX;
            else
                Ave /= m_SizeY;
        }//End if m_LinDC


        for(int J = 0; J < FastMax; J++)
        {
            int temp=0;
            int fast = J * FastScanInc;
            int index = slow+fast;

            if(!m_Derivative) // if topo/image mode
            {
                temp = round((Data[index] - Min - Ave) * ColorScale);
            }

            if(m_Derivative && J != 0)  //if Deriv
            {
                temp = round((Data[index - FastScanInc] - Data[index] - Min - Ave) * ColorScale);
            }


            temp = min(temp,255);
            temp = max(temp,0);
            m_HistogramData[temp]++;

            if(!m_Inversion)
            {
                m_BmpBits[(SlowMax-1)*SlowScanInc-slow +fast] = m_RGB[255-temp];
            }
            else
            {
                m_BmpBits[(SlowMax-1)*SlowScanInc-slow +fast] = m_RGB[temp];
            }

        }// end for
    } // end for

    return true;
}

void CWinSTMBmp::NewLUT(RGBQUAD* newRGB)
{
    memcpy(m_RGB,newRGB,sizeof(RGBQUAD)*256);

}


An error message appears after I close the window in the running program saying, 'encountered an improper argument'. I haven't found this yet in the code. Also, when I run it in debug mode I get a 'Debug Assertion Failed!' for File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\filelist.cpp, at Line: 225.

Running with CLR and Run Time Exception Throws refers to the following section of code, with a break point at:

WinSTM.exe!CWinSTMDoc::CopyDoc(CWinSTMDoc * pDocNew, int chan)  Line 486 + 0x3b bytes   C++
WinSTM.exe!CWinSTMView::CreateNewDoc(CWinSTMDoc * pDoc)  Line 2717  C++
WinSTM.exe!CWinSTMView::OnImageLinDcOffset()  Line 5052 + 0x11 bytes    C++


These calls refer to the following code:
void CWinSTMView::OnImageLinDcOffset()
{
    CWinSTMDoc *pDoc = CreateNewDoc(GetDocument());

CreateNewDoc code reference:
if(((CWinSTMApp*)AfxGetApp())->m_Default.PmtForSave)
            pNewDoc->SetModifiedFlag(true);

CopyDoc code reference:
CString OldPath = GetPathName();
	pDocNew->SetPathName(OldPath + " *");
	
	CString OldTitle = GetTitle();
	pDocNew->SetTitle(OldTitle + " *");
	pDocNew->m_Ready = true;

This brings me back to the code at the beginning. However, I am still not sure exactly what is going wrong.

Thanks for all the advice! I hope this is helpful for anyone else who is tracking down a bug in a program.

Best,

Andrew
Posted
Updated 20-Jul-11 14:48pm
v7
Comments
hakz.code 20-Jul-11 12:59pm    
As you are saying couple of pop-up menu items looks like some exceptions are thrown by your app,if you post the code it might be easy to find whats causing the issue.You can make sure each of your functions are returning proper values.
Albert Holguin 20-Jul-11 14:02pm    
I agree... post the code if you know where's its breaking for more meaningful help...
AndrewG1231 20-Jul-11 15:50pm    
I posted where I think the error is coming from. I don't think all of it contributes to the problem, but there are a few places where the message box can be triggered.
Albert Holguin 20-Jul-11 18:43pm    
what line is where the debugger asserted? the debuggers assertions tell you there's something wrong.
Chandrasekharan P 20-Jul-11 13:32pm    
why not use the debugger??

One trick that might help is to comment out most of the code then run the application on the debugger (with the option to srop on all exceptions), it is works, then add some more code and try again.

Ensure that all run-time checks are enabled.

Modify your message so that you knows which message box call display the error.

Add more validation and check to your code to help validated everything works as expected. Uses assertions.

Since you works with raw arrays and pointers, ensure that all your indexing is properly done.
 
Share this answer
 
Comments
AndrewG1231 20-Jul-11 18:18pm    
very cool, I was at least able to narrow it down quickly to the first call..thanks! I will work on the rest of the suggestions
AndrewG1231 20-Jul-11 19:54pm    
Do you mean comment out the code in the entire program or just the class I am focusing on?
Philippe Mori 20-Jul-11 23:08pm    
Well, I would suggest to first remove all code related to bitmaps. If it works, then you add some code, if it does not, you remove some code.

By the way, since m_Bitmap is the problem, you shhould but a breakpoint on each line that modify that variable. It might be easier to andd a temporary if that would check if the value is null or not.

You might also add a bunch of check on that variable in your code so that a message will be displayed if it become accidently null

You also have to verify that the variable is not cleared indirectly by wrong index/size computation in the code like when calling ZeroMermory or memcpy.

By the way, it is a bad pratice to have literal constant (like 256) in code all over the place. Uses constants or sizeof operator for thing like the size of an array to copy or clear.

It is also a bad idea to assumes that your color in your palette are int. Is it the case in 64 bit? As much as possible, you have to uses the compiler to compute size for you using sizeof operator.
Read and understand the error message !
 
Share this answer
 
Comments
Chandrasekharan P 20-Jul-11 13:36pm    
Read what?? i think you should explain a little more if you are giving him a solution
Philippe Mori 20-Jul-11 23:15pm    
This is a good point. By looking at the message, we can say that the the message was shown because m_Bitmap is null. From that, either put a breakpoint on each place where the message could be displayed or change all message except one to make them distinct. You will then be able to know at which point the problem was detected.

From that, we have to ensure that is was initialized at least once. Then we have to ensure we don't explicitly clear it and finally we have to check if is not accidently overidden (Enabling maimum run-time checks could help for that. Also adding a lot of validation would help).
YvesDaoust 21-Jul-11 9:46am    
@Chandru080: the solution was to read and understand the error message.

The original question did not mention any error information, so I could imagine that the author did not look at it. Error messages always tell a bit of the truth.
You could try instrumenting the code using Log4Net[^], or someting similar. It's also worth running the application under the debugger, enabling break on throw for CLR exceptions ...

Best regards
Espen Harlinn
 
Share this answer
 
Comments
AndrewG1231 20-Jul-11 20:49pm    
I am not sure what you mean by instrumenting the code and I have never used Log4Net. I will check them out though.
One thing I notice (and it may not be your problem) is that in your Init function, you have
if (m_Bitmap != NULL)<br />
        DeleteObject(m_Bitmap);<br />
 <br />
    // create Bitmap in memory<br />
    if (m_Bitmap == NULL)<br />
    {<br />
        ...


What I see here is your first check is if m_Bitmap is not NULL (let's assume it's not) then you delete it - but you don't set m_Bitmap equal to NULL, so your next check says if the m_Bitmap IS NULL (which it's not because you didn't set it null).

Therefore you skip over all of that block, thus you don't create the DIB section.

Just a thought.
 
Share this answer
 
Comments
AndrewG1231 20-Jul-11 16:39pm    
Really? I thought it was set to NULL in the constructor at the beginning (CWinSTMBmp::CWinSTMBmp(void)). At least I see the initialization there, does it also need to be done in the member function?
krmed 20-Jul-11 16:44pm    
Yes, you set it to null in the constructor, but you don't show where you call the Init function. The first time you call it, it will be NULL (because of the contructor), but if you call it more than once it won't be NULL for the subsequent calls. (You'll notice in my response I said "let's assume it's not NULL").
Good luck.

Sorry - I posted that as a comment instead of a reply to your comment.
AndrewG1231 20-Jul-11 19:53pm    
np, thanks for the idea!
1. I don't see where in your code you ever called CWinSTMBmp::Init(). Make sure it is called before accessing the bitmap.

2. As pointed out by krmed in Solution 3, you need to set m_Bitmap to 0 after deleting it.

3. I'm not sure whether this is correct, but in this line:
m_ImageInfo.bmiHeader.biHeight      = -sizey;

Are you sure the '-' sign is correct?

[edit] Just checked, it is a correct usage. [/edit]

4. If all else fails, set a breakpoint in CWinSTMBmp::Init() and check whether the Bitmap is successfully created. Or, even more importantly, if the function is actually being called before the bitmap is being accessed.

You might also want to check out the user comments on this site. They're quite helpful.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900