调试断言失败:下标超出 std::vector 的范围
Debug assertion failed: Subscript out of range with std::vector
我正在尝试解决此问题,这似乎我正在以超出范围的索引访问,但是VS无法在发生错误的地方停止,这使我对导致此问题的原因感到困惑。
错误:
调试断言失败!程序:。。。。文件:c:\program files\Microsoft Visual Studio 10.0\vc\include\vector 行:1440 表达式:字符串下标超出范围
该程序的作用:
有两个线程:
线程 1:
第一个线程使用 GetForegroundWindow()
查找(除其他事项外)当前窗口中的更改,检查不是在循环中发生,而是在触发WH_MOUSE_LL
事件时发生。数据被拆分为固定大小的结构,以便可以通过 tcp 发送到服务器。第一个线程,并将数据(窗口标题)记录到当前结构中的std::list
中。
if(change_in_window)
{
GetWindowTextW(hActWin,wTitle,256);
std::wstring title(wTitle);
current_struct->titles.push_back(title);
}
线程 2:
第二个线程称为查找尚未发送的结构,它将其内容放入char
缓冲区中,以便可以通过 tcp 发送它们。虽然我不知道错误到底在哪里,但从字符串或列表的错误类型来看,这是我整个应用程序中唯一使用列表/字符串的代码(其余的是常规数组)。此外,如代码注释中所述注释 if 块可阻止错误发生。
BOOL SendStruct(DATABLOCK data_block,bool sycn)
{
[..]
int _size = 0;
// Important note, when this if block is commented the error ceases to exist, so it has something to do with the following block
if(!data_block.titles.empty()) //check if std::list is empty
{
for (std::list<std::wstring>::iterator itr = data_block.titles.begin(); itr != data_block.titles.end() ; itr++) {
_size += (((*itr).size()+1) * 2);
} //calculate size required. Note the +1 is for an extra character between every title
wchar_t* wnd_wbuffer = new wchar_t[_size/2](); //allocate space
int _last = 0;
//loop through every string and every char of a string and write them down
for (std::list<std::wstring>::iterator itr = data_block.titles.begin(); itr != data_block.titles.end(); itr++)
{
for(unsigned int i = 0; i <= (itr->size()-1); i++)
{
wnd_wbuffer[i+_last] = (*itr)[i] ;
}
wnd_wbuffer[_last+itr->size()] = 0x00A6; // separator
_last += itr->size()+1;
}
unsigned char* wnd_buffer = new unsigned char[_size];
wnd_buffer = (unsigned char*)wnd_wbuffer;
h_io->header_w_size = _size;
h_io->header_io_wnd = 1;
Connect(mode,*header,conn,buffer_in_bytes,wnd_buffer,_size);
delete wnd_wbuffer;
}
else
[..]
return true;
}
我的线程同步尝试:有一个指向创建的第一个data_block的指针 (db_main)指向当前data_block的指针 (db_cur)
//datablock format
typedef struct _DATABLOCK
{
[..]
int logs[512];
std::list<std::wstring> titles;
bool bPrsd; // has this datablock been sent true/false
bool bFull; // is logs[512] full true/false
[..]
struct _DATABLOCK *next;
} DATABLOCK;
//This is what thread 1 does when it needs to register a mouse press and it is called like this:
if(change_in_window)
{
GetWindowTextW(hActWin,wTitle,256);
std::wstring title(wTitle);
current_struct->titles.push_back(title);
}
RegisterMousePress(args);
[..]
//pseudo-code to simplify things , although original function does the exact same thing.
RegisterMousePress()
{
if(it_is_full)
{
db_cur->bFull= true;
if(does db_main exist)
{
db_main = new DATABLOCK;
db_main = db_cur;
db_main->next = NULL;
}
else
{
db_cur->next = new DATABLOCK;
db_cur = db_cur->next;
db_cur->next = NULL;
}
SetEvent(eProcessed); //tell thread 2 there is at least one datablock ready
}
else
{
write_to_it();
}
}
//this is actual code and entry point of thread 2 and my attempy at synchronization
DWORD WINAPI InitQueueThread(void* Param)
{
DWORD rc;
DATABLOCK* k;
SockWClient writer;
k = db_main;
while(true)
{
rc=WaitForSingleObject(eProcessed,INFINITE);
if (rc== WAIT_OBJECT_0)
{
do
{
if(k->bPrsd)
{
continue;
}
else
{
if(!k)
{break;}
k->bPrsd = TRUE;
#ifdef DEBUG_NET
SendStruct(...);
#endif
}
if(k->next == NULL || k->next->bPrsd ==TRUE || !(k->next->bFull))
{
ResetEvent(eProcessed);
break;
}
} while (k = k->next); // next element after each loop
}
}
return 1;
}
详:
现在有些事情让我相信错误不在那里,因为子字符串错误非常罕见。我只能在按 Mouse_Down+Wnd+Tab 滚动窗口并保持一段时间时以 100% 的机会重现它(当然在其他情况下也发生了)。我避免发布整个代码,因为它有点大,混乱是不可避免的。如果错误不在这里,我将编辑帖子并添加更多代码。
提前致谢
这里似乎没有任何线程同步。如果一个线程从结构中读取,而另一个线程写入,则可能会在初始化期间读取该结构,其中包含一个包含空字符串(或介于两者之间的无效内容)的非空列表。
如果在发布的函数之外没有互斥锁或信号量,则可能是问题所在。
所有大小计算似乎对 Windows 有效,尽管我没有尝试运行它......<= … -1
而不是i <= (itr->size()-1)
中的<
和2
而不是sizeof (wchar_t)
new wchar_t[_size/2]();
有点奇怪。
代码的问题在于,虽然线程 2 正确等待数据并且线程 1 正确通知它们,但线程 2 不会阻止线程 1 在处理数据时对其执行任何操作。用于解决此类问题的典型设备是监视器模式。
它由一个互斥锁(用于保护数据,在您访问数据时保留)和一个条件变量(Windows 术语中的 = 事件)组成,它将向使用者传达有关新数据的信息。
生产者通常会获取互斥锁,生成数据,释放互斥锁,然后触发事件。
使用者更加棘手 - 它必须获取互斥锁,检查新数据是否不可用,然后使用 SignalObjectAndWait 函数等待事件,该函数暂时释放互斥锁,然后处理新获取的数据,然后释放互斥锁。
- 尝试使用 std::vector<std::thread时出现静态断言失败错误>
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- 连接和压缩标准::vector<std::字符串的最佳方法>
- C++从 std::vector<std::function<中删除 std::function>>
- 如何在构造函数初始值设定项列表中使用 n 个元素初始化 std::vector<std::time_t>
- 如何使用 CUDA 将 std::vector<std::string> 复制到 GPU 设备
- 编译错误 std::vector<std::shared_ptr<T>>迭代器和擦除方法
- 将 std::vector<std::unique_ptr<T>> 移动到 std::vector<std::shared_ptr<T>>
- 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?
- 使用 std::vector<std::future<int>> 和 std::async 启动几个线程时中止
- 为什么转置这个 std::vector<std::vector<std::string> > 这么慢?
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 在 boost::<double>asio::buffer 中使用像 std::vector<std::complex> 这样的参数
- 如何从 std::initializer_list<char const* 构建 std::vector<std::string>>
- 如何检查 std::vector<std::string> 的元素是否以某个子字符串开头?
- 在 std::vector<std::vector 中重新存储内部向量<TYPE>>
- 将 std::vector<std::string> 转换为 const char* const*
- 不能将结构push_back() 转换为 std::vector<std::shared_ptr<theStruct>> theVector
- SWIG:传递一个 std::vector< std::vector <double> >指向 python 的指针
- 将 std::vector<std::p air<const K, V>*> 转换为 std::vector<std::p air<const K, V>&g