调试断言失败,字符串下标超出范围
Posted
技术标签:
【中文标题】调试断言失败,字符串下标超出范围【英文标题】:Debug assertion failed, string subscript out of range 【发布时间】:2013-02-19 16:18:58 【问题描述】:我正在尝试编写一个函数,该函数从列表框中获取数据,检索帐户名称,然后使用 SQL 更改帐户类型。但是,由于某种原因,当列表框项包含“fdsa\t\tdungeon master”但不包含“asdf\t\tuser”时,此代码可以正常工作。在后来的测试中,它以 'auser\t\tuser' 失败。消息框功能表明正在检索正确的数据。这可能是什么原因造成的?
void ChangeAccountType(HWND hwnd, std::string NewType)
using namespace std;
string strQuery;
string strAccountName;
string strBuffer;
int nIndex = SendMessage(GetDlgItem(hwnd, IDC_LIST1), LB_GETCURSEL, 0, 0);
SendMessage(GetDlgItem(hwnd, IDC_LIST1), LB_GETTEXT, (WPARAM)nIndex, (LPARAM)strBuffer.c_str());
MessageBox(hwnd, strBuffer.c_str(), "", NULL);
for(int iii = 0; strBuffer[iii] != '\t'; iii++)
strAccountName += strBuffer[iii];
;
strQuery = "UPDATE account SET `account type` = \"" + NewType + "\" WHERE `User Name` = \"" + strAccountName + "\"";
错误似乎发生在 for 循环中的某处,因为它上方的消息框运行良好。任何建议将不胜感激。
【问题讨论】:
我认为你 100% 确定字符串中有一个 TAB? 是的,提交给listbox的字符串格式为“username + \t\t + accounttype”,listbox正确显示 我看不到您将strBuffer
设置为任何内容的任何地方,您可能忘记了一些代码吗?
没有人会提出使用std::string::c_str()
作为LPARAM~ to
LB_GETTEXT` 是一点都不好?如果您没有使用C++11
,此时您正在使用未定义的行为。即使使用C++11
,也不要这样做这个。
【参考方案1】:
string strBuffer
是一个空字符串,大小为0
,在您尝试访问strBuffer[iii]
之前,您的代码中没有任何内容会改变它,iii
等于0
。这将返回对初始化 char
的值的引用,即空终止字符。下一次,您访问位置 1
,该位置超出范围,因此行为未定义。
我怀疑您正在篡改字符串的内部char
数组数据,从而导致未定义的行为。大概是您通过c_str()
尝试修改它的一个或多个函数。这本身会导致未定义的行为。您不能将std::string
的c_str()
用作可写字符缓冲区。
来自 21.4.7.1 [string.accessors],const charT* c_str() const noexcept
和 const charT* data() const noexcept
:
要求:程序不得更改存储在字符数组中的任何值。
【讨论】:
那么为什么当我使用 'fdsa\t\tdungeonmaster' 值时它可以正常工作?这就是我开始使用 += 的原因,因为每次使用 strAccountName[iii] 都会失败。如果是这样,我将如何获取字符串的第一部分? @MatsPetersson 选项卡无关紧要,首先访问空字符串上的strBuffer[0]
。
为什么strBuffer[0]是一个空字符串,它应该包含'a'? 'a' 显示在 for 循环之前的消息框中
好的,非常感谢。对我来说仍然没有多大意义,为什么它会如此具体地中断,但如果我切换到 char[50],它就可以正常工作,所以问题基本上得到了解决。
当您需要一个需要修改的字符串缓冲区时,您不应该使用std::string::c_str()
。在C++11
之前这样做是未定义的行为,而在C++11
这样做是不好的做法。以上是关于调试断言失败,字符串下标超出范围的主要内容,如果未能解决你的问题,请参考以下文章