运行时检查失败#2 C/C++
我在程序中遇到了一个让我有些困惑的问题。我有一个程序运行良好(它在 VS 2010 上运行良好,这不是我升级到 .NET 并且这个错误开始发生的),程序主要是 c 和一些 c++(我的老板讨厌面向对象,因为它通常涉及到向他偏执的图书馆打电话,微软将停止支持,如果他们有旧版本,也必须交付给客户,这可能是一个问题,因为其中很多都是政府的,他还认为这些电话会导致不必要的开销,所以我必须尽可能避免它)然后我取消注释了一段代码(我将把这个代码块发布得稍微低一些,因为它已经从我未注释的原始代码中进行了一些修改)以开始处理它并收到错误“运行时检查错误#2“std”周围的堆栈已损坏”,其中 std 是 wchar 的 ac 样式字符串。
我试图通过实施一些不太好的修复来找出问题所在,因为如果修复有效,我就会知道实际问题是什么,然后为调试提供一个良好的基础起点。首先,我尝试增加 std 的大小,使其足够大,这样我就不会在其中放入大于它可以处理的字符串(它的值来自列表视图中不超过 3 列,每一列都不能大于 80 个字符),尽管这使我不太频繁地收到错误,但我仍然收到它。
因此,我尝试将该代码块中的 std 切换为 msg (与当时的 std 完全相同),看看 msg 是否出现相同的错误(这意味着它是由该代码块生成的),但错误仍然出现大约标准。
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 周围的金丝雀上写的一些其他变量,所以我在用 msg 替换它的所有实例后将其注释掉(除了那些它是尚未获得的函数的局部变量的变量)发生错误时尚未调用)但这只会导致错误出现在 msg 周围(实际上它也显示为函数的局部变量)。
接下来,我尝试使用 static 在堆上而不是堆栈上声明 msg(因为使用 new 会涉及我的老板,因此讨厌现代代码),但这只会发生以下错误:“HTZx86.exe 中的 0x00300030 处未处理的异常:0xC0000005:读取位置 0x00300030 时出现访问冲突。”在位置 0x00300030 处是对我无法控制的外部 API 的调用。
现在,在我对代码的其他部分进行了一些不相关的修改后,我同时随机获得 std 和 msg 周围的堆栈错误(有时在函数调用之后,有时在函数调用之前),而不是在一致的基础上以太。我想知道是否有任何好的方法来调试这个问题,因为单独的断点对我没有帮助,调用堆栈也没有帮助(尽管我可能使用它们是错误的)?
下面是变量的声明以及在调用函数之前调用它的唯一其他位置:
声明:
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);
}
}
PSExternalAPIFunction1 是存在访问冲突的地方。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
代码中布满了定时炸弹。从 FileSaveBox 开始,您在其中传递字符串缓冲区,但不告诉函数缓冲区有多长。添加大量 _swprintf、wcscpy 和 wcscat 调用,这些调用都不会检查缓冲区是否可能溢出,并且 RTC 错误很容易解释。
您知道如何使用 wcspcy_s 和 wcscat_s,使其保持一致。
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.