当前位置: 首页 > 编程日记 > 正文

STL笔记(5)条款49:学习破解有关STL的编译器诊断信息

STL笔记(5)条款49:学习破解有关STL的编译器诊断信息

条款49:学习破解有关STL的编译器诊断信息

用一个特定的大小定义一个vector是完全合法的,

vector<int> v(10);    // 建立一个大小为10的vector

而string在很多方面像vector,所以你可能希望可以这么做:

string s(10);        // 常识建立一个大小为10的string

这不能编译。string没有带有一个int实参的构造函数。我的一个STL平台像这样告诉我那一点:

example.cpp(20): error C2664:'__thiscall std::basic_string<char, struct
std::char_traits<char>,class std::allocator<char> >::std::basic_string<char,
struct std::char_traits<char>,class std::allocator<char> >(const class
std::allocator<char> &)': cannot convert parameter 1 from 'const int' to 'const
class std::allocator<char> &' Reason: cannot convert from 'const int' to 'const
class std::allocator<char>
No constructor could take the source type, or constructor overload resolution was ambiguous

是不是很奇妙?消息的第一部分看起来像一只猫走过键盘,第二部分神秘地提到了一个从未在源代码中涉及的分配器,第三部分说构造函数调用是错的。当然,第三部分是准确的,但首先让我们关注于号称猫咪散步的结果上,因为当使用string时,这是你经常遇到的诊断信息的典型。

string不是一个类,它是typedef。实际上,它是这个的typedef:

basic_string<char, char_traits<char>, allocator<char> >

这是因为字符串的C++观念已经被泛化为表示带有任意字符特性(“traits”)的任意字符类型的序列并储存在以任意分配器分类的内存中。在C++里所有类似字符串的对象实际上都是basic_string模板的实例,这就是为什么当大多数编译器发出关于“程序错误使用string”的诊断信息时会涉及类型basic_string。(一些编译器很善良,在诊断信息中会使用string的名字,但大多数不会。)通常,那样的诊断信息会明确指出basic_string(以及服务助手模板char_traits和allocator)在std名字空间里,所以常常看到错误调用string会产生提及这种类型的诊断信息:

std::basic_string<char, std::char_traits<char>, std::allocator<char> >

这十分接近于上面编译器里使用的诊断信息,但不同的编译器使用这个主题的不同变体。我使用的另一个STL平台以这种方式表示string,

basic_string<char, string_char_traits<char>, __default_alloc_template<false,0> >

string_char_traits和__default_alloc_template的名字是非标准的,但是那是生活。一些STL实现背离了标准。如果你不喜欢你当前STL实现里的背离,考虑用另一个来替换它。条款50给了你可以找到可选择实现的位置的例子。

不管编译器诊断信息怎样表示string类型,把诊断信息减少到有意义的东西的技术是一样的:用文字“string”全局替换冗繁难解的basic_string。如果你使用的是命令行编译器,通常可以很容易地用一个类似sed的程序或一种脚本语言比如perl、python或ruby来完成。(你可以在Zolman的文章——《Visual C++的STL错误信息解码器》[26]——里找到一个这样的脚本的例子。)就上面的诊断信息而言,我们用string全局替换

std::basic_string<char, struct std::char_traits<char>,
class std::allocator<char> >

可以得到这个:

example.cpp(20): error C2664:'__thiscall string::string(const class
std::allocator<char> &)': cannot convert parameter 1 from 'const int' to const
class std::allocator<char> &'

这会清楚(或至少比较清楚)地说明问题是在传给string构造函数的参数类型里,即使仍然神秘地提及allocator<char>,但比较容易使人发现不存在只带有大小的string构造函数形式。

顺便说一下,神秘地提到分配器的原因是每个标准容器都有一个只带有分配器的构造函数。就string而论,是三个可以用一个实参调用的构造函数之一,但由于某种原因,编译器指出带有分配器的那个是你试图调用的。编译器指错了,而诊断信息也令人误解。哦哟。

至于只带有分配器的构造函数,请不要使用它。那个构造函数是为了容易构造类型相同但分配器不等价的容器。通常,那是不好的,非常不好。要知道为什么,转向条款11。

现在让我们对付更富于挑战性的诊断信息。假定你正在实现一个允许用户通过昵称而不是电子邮件地址查找人的电子邮件程序。例如,这样的程序将可能使用“The Big Cheese”作为美国总统(碰巧是president@whitehouse.gov)电子邮件地址的同义词。这样的程序可以使用一个从昵称到电子邮件地址的映射,并可能提供一个成员函数showEmailAddress,显示和给定的昵称关联的电子邮件地址:

class NiftyEmailProgram {
private:
    typedef map<string, string> NicknameMap;
    NicknameMap nicknames;                // 从昵称到电子邮件
                            // 地址的映射
public:
    
    void showEmailAddress(const string& nickname) const;
};

在showEmailAddress内部,你需要找到与一个特定的昵称关联的映射入口,所以你可能这么写:

void NiftyEmailProgram::showEmailAddress(const string& nickname) const
{
    
    NicknameMap::iterator i = nicknames.find(nickname);
    if (i != nicknames. end()) 
    
}

编译器不喜欢这个,而且有好的原因,但原因不明显。为了帮助你指出它,这是一个STL平台有帮助地发出的:

example.cpp(17): error C2440: 'initializing': cannot convert from 'class
std::_Tree<class std::basic_string<char, struct std::char_traits<char>,class
std::allocator<char> >,struct std::pair<class std::basic_string<char, struct
std::char_traits<char>,class std::allocator<char> > const .class
std::basic_string<char, struct std::char_traits<char>,class std::allocator<char> >
>,struct std::map<class std::basic_string<char, struct
std::char_traits<char>,class std::allocator<char> >.class std::basic_string<char,
struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class
std::basic_string<char,structstd::char_traits<char>, class
std::allocator<char> > >,class std::allocator<class std::basic_string<char, struct,
std::char_traits<char>,class std::allocator<char> > > >::_Kfn, struct
std::less<class std::basic_string<char, struct std::char_traits<char>,class
std::allocator<char> > >,class std::allocator<class std::basic_string<char, struct,
std::char_traits<char>,class std::allocator<char> > > >::const_iterator' to 'class
std::_Tree<class std::basic_string<char, struct std::char_traits<char>,class
std::allocator<char> >,struct std::pair<class std::basic_string<char, struct
std::char_traits<char>,class std::allocator<char> > const .class
std::basic_string<char, struct std::char_traits<char>,class std::allocator<char> >
>,struct std::map<class std::basic_string<char, struct
std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,
struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class
std::basic_string<char,structstd::char_traits<char> .class
std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> > > >::_Kfn, struct
std::less<class std::basic_string<char, struct std::char_traits<char>,class
std::allocator<char> > >,class std::allocator<class std::basic_string<char, struct
std::char_traits<char>,class std::allocator<char> > > >::iterator'
No constructor could take the source type, or constructor overload resolution was ambiguous

有2095个字符长,这条消息看起来相当可怕,但我看过更糟的。对于这个例子我最喜欢的STL平台之一产生了一个4812个字节的诊断信息。正如你所猜测的,错误信息以外的特性是造成我喜爱它的原因。

让我们把这团乱麻减少成容易处理的东西。我们从把basic_string乱语替换成string开始。可以产生这个:

example.cpp(17): error C2440: 'initializing': cannot convert from 'class 
std::_Tree<class string, struct std::pair<class string const,class string >,struct std::map<class string, class string, struct std::less<class string >,class std::allocator<class string > >::_Kfn, struct std::less<class string >,class std::allocator<class string > >::const_iterator' to 'class std::_Tree<class string, struct std::pair<class string const .class string >,struct std::map<class string, class string, struct std::less<class string >,class std::allocator<class string> >::_Kfn,struct std::less<class string >,class std::allocator<class string> >::iterator' No constructor could take the source type, or constructor overload resolution was ambiguous

好多了。现在瘦身到745个字符了,我们可以真正地开始看消息了。很可能引起我们注意的东西之一是模板std::_Tree。标准没有说过一个叫_Tree的模板,但名字中的前导下划线随后有一个大写字母唤起了我们的记忆——这样的名字是为实现而保留。这是用来实现STL一些部分的一个内部模板。

实际上,几乎所有STL实现都使用某种内在的模板来实现标准关联容器(set、multiset、map和multimap)。就像使用string的源代码通常导致诊断信息提及basic_string一样,使用标准关联容器的源代码经常会导致诊断信息提及一些内在的树模板。在这里,它叫做_Tree,但我知道的其他实现使用__tree或__rb_tree,后者反映出使用红-黑树——在STL实现中最常使用的平衡树类型。(译注:红黑树的知识可以在数据结构或算法的相关书籍里找到。)

把_Tree先放到一边,上面的消息提到了一个我们得认出的类型:std::map<class string, class string, struct std::less<class string>, class std::allocator<class string > >。这正好是我们正使用的map类型,除了显示了比较和分配器类型(我们定义map时没有指定它们)。如果我们用那个类型的typedef——NicknameMap——替换了它,错误信息将更容易明白。于是产生了这个:

example.cpp(17): error C2440: 'initializing': cannot convert from 'class
std::_Tree<class string, struct std::pair<class string const, class string >,struct
NicknameMap::_Kfn, struct std::less<class string >,class std::allocator<class
string > >::const_iterator' to 'class std::_Tree<class string, struct std::pair<class
string const ,class string >,struct NicknameMap::_Kfn, struct std::less<class
string >,class std::allocator<class string > >::iterator'
No constructor could take the source type, or constructor overload resolution was ambiguous

这条信息更短,但清楚得多。我们需要对_Tree做一些事情。因为_Tree是一个实现特定(implementation-specific)的模板,知道它的模板参数的意思的唯一的方法是去读源代码,而如果不必,没有理由要去翻寻实现特定的源代码。让我们试着只是用SOMETHING替换传给的_Tree的全部东西来看看我们得到什么。这是结果:

example.cpp(17): error C2440: 'initializing': cannot convert from 'class
std::_Tree<SOMETHING>::const_iterator to 'class
std::_Tree<SOMETHING>::iterator'
No constructor could take the source type, or constructor overload resolution was ambiguous

是我们能够处理的东西。编译器抱怨我们试图把某种const_iterator转换成iterator,一次对常数正确性的明显破坏。让我们再次看看那段讨厌的代码,我已经高亮了引起编译器怒火的那行:

class NiftyEmailProgram {
private:
    typedef map<string, string> NicknameMap;
    NicknameMap nicknames;

public:
    
    void showEmailAddress(const string& nickname) const;
};

void NiftyEmailProgram::showEmailAddress(const string& nickname) const
{
    
    NicknameMap::iterator i = nicknames.find(nickname);
    if (i != nicknames.end())
    
}

有意义的唯一解释是我们试图用一个从map::find返回的const_iterator初始化i(是iterator)。那好像很古怪,因为我们是在nicknames上调用find,而nicknames在非常量对象,find因此应该返回非常量iterator。

再看看。是的,nicknames被声明为一个非常量map,但showEmailAddress是一个const成员函数,而在一个const成员函数内部,类的所有非静态数据成员都变成常量!在showEmailAddress内部,nicknames是一个常量map。突然错误信息有意义了。我们试图产生一个进入我们许诺不要修改的map中的iterator。要解决这个问题,我们必须把i改为const_iterator或我们必须使showEmailAddress成为一个非const成员函数。这两个解决方案的挑战性或许比发现错误信息的意思更少。

在本条款中,我演示了用原文替换降低错误信息的复杂度,但一旦你稍微实践,多数时间里你将可以在头脑中进行替换。我不是音乐家(我连开收音机都有困难),但别人告诉我好的音乐家可以在一瞥之间视读几个小节;他们不需要看独立的音符。有经验的STL程序员发展出一项类似的技能。他们可以不假思索地在内部把比如std::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >翻译为string。你也要发展这项技能,但在你能做到之前,记得你总是可以通过用更短的记忆术替换冗长的基于模板的类型名字来把编译器诊断信息降低到可以理解的东西。在许多场合,你要做的就是用你已经使用的typedef名字替换typedef展开。那是我们用NicknameMap替换std::map<class string, class string, struct std::less<class string >, class::allocator<class string > >时所做的。

这里有一些应该能帮助你理解有关STL的编译器消息的其它提示:

  • 对于vector和string,迭代器有时是指针,所以如果你用迭代器犯了错误,编译器诊断信息可能会提及涉及指针类型。例如,如果你的源代码涉及vector<double>::iterator,编译器消息有时会提及double*指针。(一个值得注意的例外是当你使用来自STLport的STL实现,而且你运行在调试模式。那样的话,vector和string的迭代器干脆不是指针。对STLport和它调试模式的更多信息,转向条款50。)
  • 提到back_insert_iterator、front_insert_iterator或insert_iterator的消息经常意味着你错误调用了back_inserter、front_inserter或inserter,一一对应,(back_inserter返回back_insert_iterator类型的对象,front_inserter返回front_insert_iterator类型的对象,而inserter返回insert_iterator类型的对象。关于使用这些inserter的信息,参考条款30。)如果你没有调用这些函数,你(直接或间接)调用的一些函数做了。
  • 类似地,如果你得到的一条消息提及binder1st或binder2nd,你或许错误地使用了bind1st或bind2nd。(bind1st返回binder1st类型的对象,而bind2nd返回binder2nd类型的对象。)
  • 输出迭代器(例如ostream_iterator、ostreambuf_iterators(参见条款29),和从back_inserter、front_inserter和inserter返回的迭代器)在赋值操作符内部做输出或插入工作,所以如果你错误使用了这些迭代器类型之一,你很可能得到一条消息,抱怨在你从未听说过的一个赋值操作符里的某个东西。为了明白我的意思,试着编译这段代码:
    vector<string*> v;                    // 试图打印一个
    copy(v.begin(), v.end(),                // string*指针的容器,
        ostream_iterator<string>(cout, "\n"));    // 被当作string对象
  • 你得到一条源于STL算法实现内部的错误信息(即,源代码引发的错误在<algorithm>中),也许是你试图给那算法用的类型出错了。例如,你可能传了错误种类的迭代器。要看看这样的用法错误是怎样报告的,通过把这段代码喂给你的编译器来启发(并愉快!)自己:
    list<int>::iterator i1, i2;        // 把双向迭代器
    sort(i1, i2);            // 传给一个需要
                        // 随机访问迭代器的算法
  • 你使用常见的STL组件比如vector、string或for_each算法,而编译器说不知道你在说什么,你也许没有#include一个需要的头文件。正如条款48的解释,这问题会降临在长期以来都可以顺利编译而刚移植到新平台的代码。

相关文章:

执子之手,与子偕老。你同意么?

(1):5岁的时候&#xff0c;我说我爱你。你歪着脑袋&#xff0c;眨着水晶般的大眼睛&#xff0c;疑惑地问我&#xff1a;“什么意思呀&#xff1f;” (2):15岁的时候&#xff0c;我说:"我爱你".你的脸红得像火烧云&#xff0c;头深深地低着&#xff0c;摆弄著衣襟&…

34种墨西哥植物模型 Globe Plants – Bundle 34 Mexican Plants

Globe Plants Bundle 34墨西哥植物(3D模型)包括15种3D树木、灌木和肉质植物&#xff0c;用于南美洲的风景、住宅、花园和一般景观美化目的&#xff0c;特别是墨西哥&#xff0c;具有85种独特的照片逼真质量的3D植物模型&#xff0c;具有多种形式&#xff0c;可用于您的许多场景…

Java学习总结:36(日期处理类)

日期处理类 Date类 Date类常用方法 No.方法类型描述1public Date()构造实例化Date类对象2public Date(long date)构造将数字变为Date类对象&#xff0c;long为日期时间数据3public long getTime()普通将当前的日期时间变为long型 例&#xff1a;取得当前的日期时间 package…

最强的篮球队和马尔可夫模型

打篮球经常遇到这种情况&#xff0c;11个人&#xff0c;分4、4、3共三套&#xff0c;一群人少时间玩&#xff0c;在一个失败的团队的人下阵来填补空缺。因此&#xff0c;我认为&#xff0c;&#xff0c;会不会出现一个最强组合&#xff0c;使得这4个人一直赢比赛呢&#xff1f;…

1677: [Usaco2005 Jan]Sumsets 求和

1677: [Usaco2005 Jan]Sumsets 求和 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 626 Solved: 348[Submit][Status]Description Farmer John commanded his cows to search for different sets of numbers that sum to a given number. The cows use only numbers that ar…

通过CPAN安装Perl模块

第一步&#xff0c;进入CPAN shell&#xff1a; sudo perl -MCPAN -e shell 第一次运行会问你一些问题&#xff0c;一般来说缺省答案就好 第二步&#xff0c;执行安装程序&#xff0c;例如安装LWP:UserAgent cpan>install LWP:UserAgent 还有一个二合一的命令&#xff0c;效…

Python3和Raspberry Pi最全面最直接的课程

在一门课程中学习Python 3基础知识、高级Python、科学Python、Raspberry Pi、硬件和物联网项目 教程获取&#xff1a;Python3和Raspberry Pi最全面最直接的课程 – 云桥网络-CG技术学习平台 你会学到: Python 3基础 Python 3高级概念 Raspberry Pi的设置和使用 Scientific Py…

Java学习总结:37(比较器)

比较器 Arrays类 No.方法类型描述1public static boolean equals(int [] a,int [] a2)普通判断两个数组是否相等&#xff0c;此方法被重载多次&#xff0c;可以判断各种数据类型的数组2public static void fill(int [] a,int val)普通将指定内容填充到数组中&#xff0c;此方…

探究rh6上mysql5.6的主从、半同步、GTID多线程、SSL认证主从复制

http://407711169.blog.51cto.com/6616996/1203973/转载于:https://www.cnblogs.com/zengkefu/p/5042351.html

文字转语音(jacob)

近期项目中出现在离线情况下文字转语音的需求 经过尝试发现jacob还不错 注&#xff1a;只适用于windows系统环境 以下为开发记录&#xff1a; 1.pom.xml中引入jacob.jar <dependency><groupId>com.hynnet</groupId><artifactId>jacob</artifactId&…

log4j配置说明

2019独角兽企业重金招聘Python工程师标准>>> 一.参数意义说明 输出级别的种类 ERROR、WARN、INFO、DEBUG ERROR 为严重错误 主要是程序的错误 WARN 为一般警告&#xff0c;比如session丢失 INFO 为一般要显示的信息&#xff0c;比如登录登出 DEBUG 为程序的调试信息…

Python 无法安装PyAudio问题

一、错误与原因 在Windows上没有用于Python 3.7的轮子&#xff08;预构建包&#xff09;&#xff08;有一个用于Python 2.7和3.4到3.6&#xff09;&#xff0c;因此需要在PC上准备构建环境以使用此包。因为有些软件包很难在Windows上构建&#xff0c;所以找到3.7的轮子更容易一…

7-4 水仙花数

7-4 水仙花数 水仙花数是指一个N位正整数&#xff08;N≥3&#xff09;&#xff0c;它的每个位上的数字的N次幂之和等于它本身。例如&#xff1a;153135333。本题要求编写程序,计算所有N位水仙花数。 输入格式: 输入在一行中给出一个正整数N&#xff08;3≤N≤7&#xff09;。…

Unreal Engine4 可视化虚拟现实全流程学习教程

课程目标&#xff1a; 这是一套专门为设计院&#xff0c;三维动画公司、效果图公司、景观规划公司、以及有志于进入这些行业创业的公司和人们量身定制的一套虚拟漫游高级教材。 在这套教学里面&#xff0c;我们能够从头开始了解到一个效果图级别的虚拟漫游是怎么制作出来的&…

用python的numpy作线性拟合、多项式拟合、对数拟合

转自&#xff1a;http://blog.itpub.net/12199764/viewspace-1743145/ 项目中有涉及趋势预测的工作&#xff0c;整理一下这3种拟合方法&#xff1a;1、线性拟合-使用mathimport mathdef linefit(x , y): N float(len(x)) sx,sy,sxx,syy,sxy0,0,0,0,0 for i in range(…

Java中的简单工厂模式(转)

Java中的简单工厂模式 举两个例子以快速明白Java中的简单工厂模式&#xff1a;女娲抟土造人话说&#xff1a;“天地开辟&#xff0c;未有人民&#xff0c;女娲抟土为人。”女娲需要用土造出一个个的人&#xff0c;但在女娲造出人之前&#xff0c;人的概念只存在于女娲的思想里面…

Math.toRadians()与 Math.toDegrees()方法介绍

strictfp 的意思是FP-strict,也就是说精确浮点的意思。在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时,Java的编译器以及运 行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。因此如果你想让你的浮点运算更加精确, 而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,可以用关键字strictfp.

Linux命令基础6-mkdir命令

mkdir是英文单词make directory的缩写。mkdir就是用来创建路径&#xff0c;一般就是用来创建文件夹的。 语法 mkdir (选项)(参数) 选项 -Z&#xff1a;设置安全上下文&#xff0c;当使用SELinux时有效&#xff1b; -m<目标属性>或--mode<目标属性>建立目录的同时设…

原子性,可见性,有序性详解及DCL单例模式两次校验的目的(拓展懒汉式,饿汉式)

进入以后进行第二次判断,是因为,对于首个拿锁者,它的时段instance肯定为null,那么进入new Singleton()对象创建,而在首个拿锁者的创建对象期间,可能有其他线程同步调用getInstance(),那么它们也会通过if进入到同步块试图拿锁然后阻塞。如果能够保证2,3的顺序那么就不会存在安全问题,但是实际因为JIT和处理器会对代码进行优化重排序,那么可能会2,3的顺序颠倒,那么就有可能会出现一个线程拿到了一个未被初始完成的对象,从而引发安全问题。,那么在这种情况下,会出现多个实例对象。

3ds Max中的V-Ray学习

时长3h 30m 大小解压后&#xff1a;2.73G 包含项目文件 1280X720 MP4 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 3ds Max中的V-Ray简介:官方V-Ray导师 云桥网络 获取课程&#xff1a;3ds Max中的V-Ray学习 Introduction To V-Ray in 3…

7-5 二分法求多项式单根 (20分)

二分法求函数根的原理为&#xff1a;如果连续函数f(x)在区间[a,b]的两个端点取值异号&#xff0c;即f(a)f(b)<0&#xff0c;则它在这个区间内至少存在1个根r&#xff0c;即f( r )0。 二分法的步骤为&#xff1a; 检查区间长度&#xff0c;如果小于给定阈值&#xff0c;则停…

JAVA的instanceOf什么时候用

我个人理解的一个应用场合就是&#xff0c;当你拿到一个对象的引用时&#xff08;例如参数&#xff09;&#xff0c;你可能需要判断这个引用真正指向的类。所以你需要从该类继承树的最底层开始&#xff0c;使用instanceof操作符判断&#xff0c;第一个结果为true的类即为引用真…

解决谷歌浏览器在非https下限制获取多媒体对象(音视频)的解决方式

1、浏览器输入&#xff1a;chrome://flags/ 2、输入你要允许的域名地址或ip端口地址&#xff08;如下图&#xff09;

After Effects CS4 期末考试卷

AECS4考试A卷转载于:https://blog.51cto.com/hnxdd/1593985

数据图表之圆柱图

需求是这样的&#xff0c;需要一个圆柱实现展示内存的占用变化。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><style>.column{position: relative;width: 300px;height:…

虚幻引擎5–环境设计学习教程

时长:1h 12m |视频:. MP4 1280720&#xff0c;30 fps(r) |音频:AAC&#xff0c;48000 Hz&#xff0c;2ch |大小解压后:1.08G 含课程文件 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09; 在这节课中&#xff0c;你将学习如何在虚幻引擎5中从…

Java学习总结:38(正则表达式)

正则表达式 正则表达式本质上是一种字符串操作语法规则&#xff0c;利用它我们能更加灵活地实现字符串的匹配、拆分、替换等操作。 正则标记 所有的正则表达式支持的类都定义在java.util.regex包里面。这个包里面定义了如下两个主要的类&#xff1a; 1.Pattern类&#xff1a…

PHP Multipart/form-data remote dos Vulnerability

catalog 1. Description 2. Analysis 1. Description PHP is vulnerable to a remote denial of service, caused by repeatedly allocate memory、concatenate string、copy string and free memory when PHP parses header areas of body part of HTTP request with multipar…

HTTP的KeepAlive是开启还是关闭?

转自&#xff1a;http://blog.csdn.net/gaogaoshan/article/details/38580013 1、KeepAlive的概念与优势 HTTP的KeepAlive就是浏览器和服务端之间保持长连接&#xff0c;这个连接是可以复用的。当客户端发送一次请求&#xff0c;收到相应内容后&#xff0c;这个连接会保持一段时…

MyBatis中jdbcType=INTEGER、VARCHAR作用

Mapper.xml中 pid #{pid,jdbcTypeINTEGER} pid #{pid} 都可以用 Mybatis中什么时候应该声明jdbcType&#xff1f; 当Mybatis不能自动识别你传入对象的类型时。 什么情况下&#xff0c;Mybatis不能自动识别我的传入类型&#xff1f; 例如&#xff1a;当你传入空值的时候。&…