views:

63

answers:

1

Hi all, I have encountered a problem in my program that has me somewhat stumped. I had a program that was working fine (it was working fine on VS 2010 this is not an I upgraded to .NET and this error started happening post) with a program that is mostly c and some c++ (my boss HATES object oriented since it usually involves making calls to libraries that he is paranoid microsoft will stop supporting and would also have to be delivered to the customer if they have an older version which could be a problem since a lot of them are government and he also thinks that these calls cause unnecessary overhead so I have to try to avoid it as much as possible) then I uncommented a block of code (I will post this block a little lower as it has been modified some from the original one I uncomented) to start working on it and got the error "Runtime check error #2 the stack around "std" has been corrupted" where std is a c style string of wchar.

I tried to figure out what the problem was by implementing some of the not so good fixes since if one works I will know what the actual problem is and then have a good base starting point for debugging. First I tried to increase the size of std to make it large enough that I wouldn't be putting a string larger than it can handle in it (it's values come from no more than 3 columns from a list view each of which can't be bigger than 80 characters) and even though this made me get the error less often I still got it.

So I tried switching std in that block of code to msg (which was exactly the same as std at the time) to see if msg got the same error (which would mean it was produced by that block of code) but the error still came up around std.

case IDC_TXT:
                    //FileSaveBox(hwnd, L"Save as...",L"Text Files (*.txt)\0*.txt\0All Files\0*.*\0",L"*.txt",wFileName);
                    FileSaveBox(hwnd, L"Save as...",L"CSV (Coma delimited) (*.csv)\0*.csv\0All Files\0*.*\0",L"*.csv",wFileName);

                        if(wcslen(wFileName)==0) return 0;

                        fin.open(wFileName);
                        if(fin.is_open())
                            val=MessageBox(hwnd,L"This file allready exists. Do you want to overwrite it?",L"Confirm Save", MB_YESNO);
                        fin.close();

                        if (val == IDNO)
                            return 0;

                        fout.open(wFileName);
                        if(!fout.is_open()) return 0;

                        /*if ((fp = _wfopen (wFileName, L"w"))==NULL)   
                        {
                            Message("Cannot Open File");
                            return 0;
                        }*/

                        _swprintf(msg,L"Some string");
                        if(im.col3)
                            wcscat(msg,L", another string");

                        fout << msg << L"\n";

                        count = ListView_GetItemCount(hlvim);
                        for(i=0;i<count;i++) 
                        {
                                ListView_GetItemText(hlvim,i,0,msg,240);
                                wcscat(msg,L", ");
                                ListView_GetItemText(hlvim,i,1,temp,80);
                                wcscat(msg,temp);
                                if(im.col3)
                                {
                                    wcscat(msg,L", ");
                                    ListView_GetItemText(hlvim,i,2,temp,80);
                                    wcscat(msg,temp);
                                }

                                fout << msg << L"\n";

                            //fprintf(fp,"%s\n",msg);
                        }
                        //fclose(fp);
                        fout.close();
                        SetFocus(hwnd);
                        return 0;

This made me think that maybe it was just some other variable writing over the canary around std so I commented it out after replacing all instances of it with msg (execpt for the ones where it is a local variable to a function that hasn't gotten called yet when the error occurs) but this just caused the error to appear around msg (which actually also shows up as a local variable to a function).

Next I tried declaring msg on the heap instead of the stack by using static (since using new would involve my bosses so hated modern code) but this only cased the following error to occur: "Unhandled exception at 0x00300030 in HTZx86.exe: 0xC0000005: Access violation reading location 0x00300030." and at location 0x00300030 is a call to an external API which I have no control over.

Now after I have made some unrelated modifications to other parts of my code I randomly get the stack arror around std and msg at the same time (sometimes after the function call and sometimes before) and not on a consistent basis ether. I would like to know if there is any good way to debugged this problem since break points alone aren't helping me and neither is the call stack (although I may be using them wrong)?

Bellow are the declarations of the variables and the only other place where it would be called before the function gets called:

Declarations:

int i,j,k,count,val,ntx,nrx,IsActive, rxcount;
    BOOL callsign, map2rx, rxhit;
    double f1,f2,f3;
    WCHAR str[80];
    static WCHAR msg[240];
    WCHAR temp[80];
    static short dir;
    //FILE* fp;
    std::wofstream fout;
    std::wifstream fin;
    LV_COLUMN pcol;
    LV_ITEM pit, pit2;
    static HWND hlvtx;
    static HWND hlvrx;
    static HWND hlvim;

and other calls:

count = ExternalAPIFunction2t();
            for(i=0;i<count;i++)
            {
                ntx = _wtoi(ExternalAPIFunction1(i+1,_SP_NBTXCH));
                nrx = _wtoi(ExternalAPIFunction1(i+1,_SP_NBRXCH));
                IsActive = _wtoi(ExternalAPIFunction1(i+1,_SP_ISACTIVE));

                try
                {
                for(j=0;j<ntx && IsActive;j++)
                {
                    f1 = _wtof(ExternalAPIFunction1(i+1,_SP_TXCH01+j));
                    _swprintf(msg,L"%09.4f MHz",f1);

                    pit.mask = LVIF_TEXT|LVIF_PARAM;
                    pit.iItem = j;
                    pit.iSubItem = 0;
                    pit.lParam = j; 
                    wcscpy_s(msg,ExternalAPIFunction1(i+1,_SP_CALLSIGN));
                    wcscat_s(msg,L"_CH");
                    _itow(j+1,temp,80);
                    wcscat_s(msg,temp);
                    pit.pszText = msg;
                    ListView_InsertItem(hlvtx,&pit);
                    _swprintf(msg,L"%.4f",f1);
                    pit.mask = LVIF_TEXT;
                    pit.iSubItem = 1;   
                    pit.pszText = msg;
                    ListView_SetItem(hlvtx,&pit);
                    f1 = _wtof(ExternalAPIFunction1(i+1,_SP_NOMINALPOWER));
                    _swprintf(msg,L"%.1f",f1);
                    pit.iSubItem = 2;   
                    pit.pszText = msg;
                    ListView_SetItem(hlvtx,&pit);
                    _swprintf(msg,L"%f",i+1);
                    pit.iSubItem = 3;   
                    pit.pszText = msg;
                    ListView_SetItem(hlvtx,&pit);           

                }
                }catch(std::exception &e)
                {
                    MessageBox(hwnd,(wchar_t*) e.what(),L"Error", MB_OK);
                }

                for(j=0;j<nrx && IsActive;j++)
                {
                    f1 = _wtof(ExternalAPIFunction1(i+1,_SP_RXCH01+j));
                    pit.mask = LVIF_TEXT|LVIF_PARAM;
                    pit.iItem = j;
                    pit.iSubItem = 0;
                    pit.lParam = j; 
                    wcscpy(msg,ExternalAPIFunction1(i+1,_SP_CALLSIGN));
                    wcscat(msg,L"_CH");
                    _itow(j+1,temp,10);
                    wcscat(msg,temp);
                    pit.pszText = msg;
                    ListView_InsertItem(hlvrx,&pit);
                    _swprintf(msg,L"%.4f",f1);
                    pit.mask = LVIF_TEXT;
                    pit.iSubItem = 1;   
                    pit.pszText = msg;
                    ListView_SetItem(hlvrx,&pit);
                    f1 = _wtof(ExternalAPIFunction1(i+1,_SP_RXBANDWIDTH));
                    _swprintf(msg,L"%.2f",f1);
                    pit.iSubItem = 2;   
                    pit.pszText = msg;
                    ListView_SetItem(hlvrx,&pit);
                    _swprintf(msg,L"%f",i+1);
                    pit.iSubItem = 3;   
                    pit.pszText = msg;
                    ListView_SetItem(hlvrx,&pit);
                }
            }

P.S. ExternalAPIFunction1 was the one with the access violation.

+1  A: 

The code is littered with time bombs. That starts with FileSaveBox where you pass a string buffer but don't tell the function how long the buffer is. Add copious amounts of _swprintf, wcscpy and wcscat calls, none of which checks if the buffer may overrun and the RTC error is easily explained.

You know how to use wcspcy_s and wcscat_s, make it consistent.

Hans Passant
I'll try that and see what happens, as for the file save box it's a function in the API that I have to use instead of the the one that I can call from windows (since if the code is used in another country the buttons will be in one language but the text in another, and it calls libraries that my boss hates as well). And btw is there a secure vertion of _swprintf?
This can have little to do with what your boss hates, only solid coding is needed. Fix that API, it is broken. snwprintf or snwprintf_s.
Hans Passant
Unfortunately I'm not in a position to be able to get the API fixed :(
I ran it a couple times and got an assert for buffer too small and have increased to buffer size to fit, so it looks like that may have fixed my problem with debuggin. Thanks