代码之家  ›  专栏  ›  技术社区  ›  njvb

运行时检查失败2 c/c++

  •  0
  • njvb  · 技术社区  · 14 年前

    我在程序中遇到了一个问题,使我有点难堪。我有一个程序工作得很好(它在VS 2010上工作得很好,这不是我升级到.NET,这个错误开始发生的帖子)一个程序主要是C和一些C++(我的老板讨厌面向对象),因为它通常涉及给图书馆打电话,他偏执的微软将停止支持,也必须是D。如果客户有一个旧版本,这可能是一个问题,因为他们中的很多是政府的,他还认为这些调用会导致不必要的开销,所以我必须尽量避免这样做),然后我取消了一个代码块的注释(我会将这个块略低一点,因为它已经从原来的一些修改了一些其中一个i uncented)开始处理它并得到错误“runtime check error”2“std”周围的堆栈已损坏,其中std是wchar的C样式字符串。

    我试图通过实现一些不太好的修复来找出问题所在,因为如果一个修复有效,我将知道实际问题是什么,然后有一个良好的调试基础起点。首先,我尝试增加std的大小,使其足够大,这样我就不会在其中放置一个比它能处理的更大的字符串(它的值来自一个列表视图中不超过3列的值,每个列不能超过80个字符),即使这使我得到错误的频率更低,我仍然得到它。

    所以我尝试将该代码块中的std切换为msg(当时与std完全相同),以查看msg是否有相同的错误(这意味着它是由该代码块生成的),但错误仍然出现在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;
    

    这让我觉得这可能只是一些其他变量在std周围写在canary上,所以我在用msg替换了它的所有实例(execpt是一个局部变量,函数在发生错误时还没有被调用)之后就把它注释掉了,但这只会导致错误出现在msg周围(实际上是也显示为函数的局部变量)。

    接下来,我尝试使用static在堆上声明msg,而不是堆栈上声明msg(因为使用new会让我的老板非常讨厌现代代码),但这只会导致出现以下错误:“htzx86.exe中的0x0300030处未处理的异常:0xc000005:访问冲突读取位置0x0300030。”并且在位置0x0300030处是对外部代码的调用。我无法控制的API。

    现在,在我对代码的其他部分做了一些不相关的修改之后,我同时(有时在函数调用之后,有时在函数调用之前)随机地得到std和msg周围的堆栈arror,而不是基于一致的ether。我想知道是否有任何好的方法来调试这个问题,因为只有断点对我没有帮助,调用堆栈也没有帮助(尽管我可能使用它们是错误的)?

    以下是变量的声明,以及调用函数之前调用变量的唯一其他位置:

    声明:

    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;
    

    以及其他电话:

    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.ExternalAPI函数1是具有访问冲突的函数。

    1 回复  |  直到 11 年前
        1
  •  1
  •   Hans Passant    14 年前

    代码中到处都是定时炸弹。从filesavebox开始,在这里传递一个字符串缓冲区,但不要告诉函数缓冲区有多长。添加大量的swprintf、wcspy和wcscat调用,这些调用都不会检查缓冲区是否可能溢出,并且可以很容易地解释rtc错误。

    你知道如何使用wcspcy和wcscapt,使其一致。

    推荐文章