关于STL迭代器end()的问题

DDGG 2009-01-19 02:57:52
最近在对一个经常崩溃的程序进行查错,这个程序是网络传输方面的,其中收发数据用到了STL的string。
有一个问题不是很清楚,就是:对于一个容器的end()返回的迭代器是否是一个指向可读内存区域的有效指针?

我的程序中有类似这样的代码:

void CIPCConnection::OnReceived( const char *pData, DWORD nLen )
{
vector<string> vecParam;
string strMessage;
string strSection;
int iTemp;

m_strMessageBuf.resize(m_strMessageBuf.size() + nLen);
// 从VC6转到VS2003的时候发现 const_cast<char *>(m_strMessageBuf.end()) 这样写不能通过编译!所以在下面加了&*
char *p = const_cast<char *>(&*m_strMessageBuf.end()) - nLen; // 有一次崩溃我选择调试,查看堆栈发现出错点在这里!
memcpy(p, pData, nLen);

while ((iTemp = m_strMessageBuf.find_first_of('\0')) != string::npos)
{
pData = m_strMessageBuf.data();
for (int i=0; i<iTemp; i++)
{
if (pData[i] == '|')
{
vecParam.push_back(strSection);
strSection = "";
}
else
strSection += pData[i];
}

if (!strSection.empty())
{
vecParam.push_back(strSection);
strSection = "";
}

if (vecParam.size())
{
strMessage = vecParam.front();
vecParam.erase(vecParam.begin());
}

CIPCServer *pIPCServer = dynamic_cast<CIPCServer *>(m_pParent);
if (pIPCServer)
{
pIPCServer->OnMessage(this, strMessage, vecParam);
}

vecParam.clear();
m_strMessageBuf.erase(0, iTemp + 1);
}
}


网上找到一篇文章提到说对end()返回的迭代器解引用是不安全的,但不知是否权威。
http://www.builder.com.cn/2007/1210/678099.shtml
...全文
607 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
DDGG 2009-01-19
  • 打赏
  • 举报
回复
m_strMessageBuf.insert(m_strMessageBuf.size(), pData, nLen);

我改成这样了,呵呵。
Wolf0403 2009-01-19
  • 打赏
  • 举报
回复
    char *p = const_cast<char *>(&*m_strMessageBuf.end()) - nLen;  // 有一次崩溃我选择调试,查看堆栈发现出错点在这里!
memcpy(p, pData, nLen);



改用
copy (pData, pData + nLen, m_strMessageBuf.begin())
tangshuiling 2009-01-19
  • 打赏
  • 举报
回复
需要对end()获取的指针解引用,楼主你确信代码有这种需求吗?如果可以通过其他的方式解决问题,何须冒如此风险?
DDGG 2009-01-19
  • 打赏
  • 举报
回复
好的。。。我回去改一下,谢谢!
taodm 2009-01-19
  • 打赏
  • 举报
回复
“实际得到的是一个指针,运行时并不一定会真的对end()进行解引用吧? ”
你的编译器已经明明白白告诉你它真的对end()进行解引用了。
你还在幻想啥呢?
xiaoyisnail 2009-01-19
  • 打赏
  • 举报
回复
from c++ primer:
Because the iterator returned from end does not denote an element, it may not be incremented or dereferenced.


"再说 const_cast <char *>(&*m_strMessageBuf.end()) 这样的写法只是为了使编译通过,实际得到的是一个指"针,运行时并不一定会真的对end()进行解引用吧? "
晕,这样当然解引用啦
lymastee 2009-01-19
  • 打赏
  • 举报
回复
注意begin() end() front() back()的区别~~~
end()返回的不是最后一个元素...
nullah 2009-01-19
  • 打赏
  • 举报
回复
up
DDGG 2009-01-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 xiaoyisnail 的回复:]
end()返回的迭代器指向容器最后一个元素之后的位置
[/Quote]

这我知道,但我不知道STL的实现中有没有在分配内存的时候就多分配一个,从而保证end()的引用有效。
因为STL的文档好像没有明确提及不能对end()解引用。
http://www.cppreference.com/wiki/stl/iterators

再说 const_cast<char *>(&*m_strMessageBuf.end()) 这样的写法只是为了使编译通过,实际得到的是一个指针,运行时并不一定会真的对end()进行解引用吧?

查看了反汇编的代码,有人看得懂吗?

	string strMessage;
string strSection;
int iTemp;

m_strMessageBuf.resize(m_strMessageBuf.size() + nLen);
char *p = const_cast<char *>(&*m_strMessageBuf.end()) - nLen;
00434500 test eax,eax
00434502 jne CIPCConnection::OnReceived+0BAh (43450Ah)
00434504 call dword ptr [__imp___invalid_parameter_noinfo (466404h)]
0043450A mov ecx,dword ptr [edi]
0043450C call dword ptr [__imp_std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Myptr (4661C8h)]
00434512 mov ecx,dword ptr [edi]
00434514 add eax,dword ptr [ecx+14h]
00434517 cmp dword ptr [edi+4],eax
0043451A jb CIPCConnection::OnReceived+0D2h (434522h)
0043451C call dword ptr [__imp___invalid_parameter_noinfo (466404h)]
00434522 mov eax,dword ptr [edi+4]
memcpy(p, pData, nLen);
00434525 push esi
00434526 sub eax,esi
00434528 push ebp
00434529 push eax
0043452A call memcpy (455A96h)
0043452F add esp,0Ch
jiangheng2008 2009-01-19
  • 打赏
  • 举报
回复
end()返回最后一个元素的下一位置的迭代器。因此对其解引用未定义。begin(),end()类似数学中的范围[a, b)
taodm 2009-01-19
  • 打赏
  • 举报
回复
你程序已经明明白白证明给你“对end()返回的迭代器解引用是不安全的”,这还不够么。
xiaoyisnail 2009-01-19
  • 打赏
  • 举报
回复
对end()返回的迭代器解引用当然不安全,未定义行为
xiaoyisnail 2009-01-19
  • 打赏
  • 举报
回复
end()返回的迭代器指向容器最后一个元素之后的位置

64,670

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧