技术文被diss了_技术学院_宜昌市隼壹珍商贸有限公司

您好,欢迎访问宜昌市隼壹珍商贸有限公司

400 890 5375
当前位置: 主页 > 新闻动态 > 技术学院

技术文被diss了

发布时间:2025-07-19  |  点击率:

你好,雨乐!

昨晚(2025年5月10日)19:33,我突然收到了一条文章评论。

当时我心里一惊,怀疑是我上篇文章中的代码在从编辑器复制到文章时出现了错误。然而,我觉得这不太可能,因为每篇文章的代码都是在机器上运行验证后才发布的,所以出错的概率应该很低。

但既然有读者提出了问题,我必须认真验证一番。遗憾的是当时我在地铁上,无法使用电脑进行实操验证,于是我使用了一个在线编辑器,编写了一个简单的代码来进行测试:

测试结果显示没有问题。尽管如此,既然有读者反馈说在使用中存在问题,这应该不是无中生有,于是我找到了几位朋友在线帮忙查看。

这个:

这个:

还有这个:

从大家的反馈来看,仍然无法确定问题所在,大家都只是觉得可能有问题。

终于回到家后,趁着孩子在玩,我赶紧拿出电脑,把文章中的代码重新复制、编译、运行,一切正常。这就奇怪了,难道路径不同导致结果不同吗?

环境不同?我突然想起群里一位同学之前私聊过我,说他运行文章中的代码时会崩溃。

因为之前忙于工作,我没有仔细了解。在咨询了这位同学后,他回复说是在Windows下编译运行的。

由于本地没有Windows环境,我找人帮忙在VS上执行了代码,结果如下:

在Windows上出现了错误,看来该读者是在Windows环境下执行这段代码的。

既然在Windows和Linux上的运行结果不同,有必要深入研究源码实现。

MSVC实现了vector::reserve(),实现如下:

代码语言:javascript代码运行次数:0运行复制```javascript _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) { // ... _Reallocate_exactly(_Newcapacity); // ... }

从上述代码来看,我们只需要关注_Reallocate_exactly的实现即可,于是继续查看该函数的实现,如下:

代码语言:javascript代码运行次数:0运行复制javascript _CONSTEXPR20 void _Reallocate_exactly(const size_type _Newcapacity) { // set capacity to _Newcapacity (without geometric growth), provide strong guarantee auto& _Al = _Getal(); auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; const auto _Size = static_castzuojiankuohaophpcnsize_typeyoujiankuohaophpcn(_Mylast - _Myfirst); const pointer _Newvec = _Al.allocate(_Newcapacity); // ... }zuojiankuohaophpcn/size_typeyoujiankuohaophpcn

我们注意到vector::reserve中获取了_Myfirst和_Mylast(注意,此处_Myfirst == _Mylast),然后调用allocator.allocate()函数分配了内存,那么继续看vector::operator[]的实现,如下:

代码语言:javascript代码运行次数:0运行复制javascript _NODISCARD _CONSTEXPR20 const _Ty& operator[](const size_type _Pos) const noexcept / strengthened / { auto& _My_data = _Mypair._Myval2;#if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( _Pos (_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range");#endif // _CONTAINER_DEBUG_LEVEL > 0 return _My_data._Myfirst[_Pos]; }


我们注意到上面一句代码_Pos zuojiankuohaophpcn (_My_data._Mylast - _My_data._Myfirst),在前面内容中,有提到_Myfirst == _Mylast,因此该处代码不成立,所以引发了崩溃,这就是Windows下运行结果出错的原因。

GNU实现gnu下vector::reserve()实现如下:

代码语言:javascript代码运行次数:0运行复制javascript templatezuojiankuohaophpcntypename _alloc="" _tp="" typename=""youjiankuohaophpcn void vectorzuojiankuohaophpcn_tp _alloc=""youjiankuohaophpcn:: reserve(size_type __n) { if (__n youjiankuohaophpcn this-youjiankuohaophpcnmax_size()) __throw_length_error(__N("vector::reserve")); if (this-youjiankuohaophpcncapacity() zuojiankuohaophpcn __n) { const size_type __old_size = size(); pointer __tmp = _M_allocate(__n); this-youjiankuohaophpcn_M_impl._M_finish = _GLIBCXX_MAKE_MOVE_ITERATOR(this-youjiankuohaophpcn_M_impl._M_start), _GLIBCXX_MAKE_MOVE_ITERATOR(this-youjiankuohaophpcn_M_impl._M_finish)); std::_Destroy(this-youjiankuohaophpcn_M_impl._M_start, this-youjiankuohaophpcn_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this-youjiankuohaophpcn_M_impl._M_start, this-youjiankuohaophpcn_M_impl._M_end_of_storage - this-youjiankuohaophpcn_M_impl._M_start); this-youjiankuohaophpcn_M_impl._M_start = __tmp; this-youjiankuohaophpcn_M_impl._M_finish = __tmp + __old_size; this-youjiankuohaophpcn_M_impl._M_end_of_storage = this-youjiankuohaophpcn_M_impl._M_start + __n; } } }zuojiankuohaophpcn/_tpyoujiankuohaophpcnzuojiankuohaophpcn/typenameyoujiankuohaophpcn

从上述实现可以看出,reserve()函数分配了所需的内存空间,并且与MSVC一样的是经过reserve之后_M_start == _M_finish,这是因为__old_size为0。

我们继续查看vector::operator[]的实现,如下所示:

代码语言:javascript代码运行次数:0运行复制javascript const_reference operator[](size_type n) const { return *(this->_M_impl._M_start + n); }

与MSVC的operator实现不同的是,gnu的实现中,直接通过首地址+n来进行元素访问(而没有进行size判断),因为内存已经完成分配,所以这样操作是没问题的,这就是Linux环境下执行没问题的原因。

结语本想与该读者继续私聊,无奈已经被取消关注?。

昨晚,我也对读者提出的问题进行了反思。虽然代码在Linux环境下运行没有问题,但仍然会有一部分Windows的读者认为代码有误。因此,在未来的文章中,如果涉及到代码,我会尽量考虑编译环境的因素。

今天的文章就到这里,我们下期见!

全国统一服务电话

400 890 5375

电子邮箱:879577@qq.com

公司地址:宜昌市西陵区黄河路5号三峡明珠10栋1051室

咨询微信

TEL:13680874598