1.许多Windows程序中的变量名使用一种称作「匈牙利表示法」的命名系统,该系统在变量名称前面增加了表示变量数据型态的短前缀。前缀i表示int、sz表示「以零结束的字符串」。
前128个Unicode字符(16位代码从0x0000到0x007F)就是ASCII字符,而接下来的128个Unicode字符(代码从0x0080到0x00FF)是ISO 8859-1对ASCII的扩展。Unicode中不同部分的字符都同样基于现有的标准。这是为了便于转换。希腊字母表使用从0x0370到0x03FF的代码,斯拉夫语使用从0x0400到0x04FF的代码,美国使用从0x0530到0x058F的代码,希伯来语使用从0x0590到0x05FF的代码。中国、日本和韩国的象形文字(总称为CJK)占用了从0x3000到0x9FFF的代码。
0x0000 ~ 0x007F ->ASCII字符
0x0080 ~ 0x00FF ->ISO 8859-1
0x0370 ~ 0x-03FF ->希腊字母
0x3000 ~ 0x9FFF ->CJK
美国标准
早期计算机的字符码是从Hollerith卡片(号称不能被折迭、卷曲或毁伤)发展而来的,该卡片由Herman Hollerith发明并首次在1890年的美国人口普查中使用。6位字符码系统BCDIC(Binary-Coded Decimal Interchange Code:二进制编码十进制交换编码)源自Hollerith代码,在60年代逐步扩展为8位EBCDIC,并一直是IBM大型主机的标准,但没使用在其它地方。
美国信息交换标准码(ASCII:American Standard Code for Information Interchange)起始于50年代后期,最后完成于1967年。开发ASCII的过程中,在字符长度是6位、7位还是8位的问题上产生了很大的争议。从可靠性的观点来看不应使用替换字符,因此ASCII不能是6位编码,但由于费用的原因也排除了8位版本的方案(当时每位的储存空间成本仍很昂贵)。这样,最终的字符码就有26个小写字母、26个大写字母、10个数字、32个符号、33个句柄和一个空格,总共128个字符码。ASCII现在记录在ANSI X3.4-1986字符集-用于信息交换的7位美国国家标准码(7-Bit ASCII:7-Bit American National Standard Code for Information Interchange),由美国国家标准协会(American National Standards Institute)发布。图2-1中所示的ASCII字符码与ANSI文件中的格式相似。
ASCII有许多优点。例如,26个字母代码是连续的(在EBCDIC代码中就不是这样的);大写字母和小写字母可通过改变一位数据而相互转化;10个数字的代码可从数值本身方便地得到(在BCDIC代码中,字符「0」的编码在字符「9」的后面!)
最棒的是,ASCII是一个非常可靠的标准。在键盘、视讯显示卡、系统硬件、打印机、字体文件、操作系统和Internet上,其它标准都不如ASCII码流行而且根深蒂固。
TCP/IP
proto local address foreign address state
TCP 127.0.0.1:12610 127.0.0.1:8307 ESTABLISHED
TCP 127.0.0.1:12626 127.0.0.1:12627 ESTABLISHED
TCP 127.0.0.1:12627 127.0.0.1:12626 ESTABLISHED
TCP 127.0.0.1:30003 127.0.0.1:22819 TIME_WAIT
TCP 192.168.0.117:139 0.0.0.0:0 LISTENING
TCP 192.168.0.117:1494 221.238.25.165:20014 ESTABLISHED
TCP 192.168.0.117:10562 223.214.82.243:8843 ESTABLISHED
TCP 192.168.0.117:10637 115.205.238.117:52481 ESTABLISHED
TCP 192.168.0.117:10637 120.42.243.116:4219 ESTABLISHED
TCP 192.168.0.117:12600 23.11.163.51:443 CLOSE_WAIT
客户机SOCK初始状态CLOSE_WAIT ,然后客户机往服务器连接请求 (发送SYN包),同时客户机会把SOCK状态置为SYN_SENT,
服务接收到SYN包后,返回SYN+ACK, 客户机需要发一个ACK包 回应表示连接上了,然后状态置为 ESTABLISHED
如果服务器拒绝或者找不到目标主机 就会返回CLOSE,
如果服务器 SOCK绑定到某个端口,那么状态就是LISTENING
ESTABLISHED的关闭 1. 应用程序关闭 (发送FIN包)调用 2. 操作系统关闭
stack around the variable “” was corrupted问题
把 project->配置属性->c/c++->代码生成->基本运行时检查 为 默认值 就不会报本异常
运行时提示_BLOCK_TYPE_IS_VALID_(pHead->nBlockUse)错误可能原因
1)内存越界写东西;2)这块内存已经被释放了,又被重复释放了一次。 (在第一次被释放中,是内存分配程序改掉了头部信息)。
Windows结构异常有如下几个特性:
1、它使用__try、__except、__finally和__leave关键字和RaiseException API;
2、它由Windows所支持,因此它不适合其它操作系统
3、它不处理C++对象的解析
说明:在使用Windows结构异常的函数内,如果有C++对象,编译器会发
出:error C2712: Cannot use __try in functions that require object unwinding 的错误。
如:
void fun( )
{
CObject object ; // 错误!结构化异常无法解析C++ 对象
__try{
...
}
__except(...){
...
}
}
4、它用为硬件异常(例如访问非法或被零除)或操作系统异常的结果被抛出。
也可以作为RaiseException函数的结果被抛出;
而C++异常的特点是:
1、使用try、throw和catch等关键字;
2、它处理C++对象的解析;
3、它作为throw语句的结果被抛出;
注:MFC提供了第三种异常处理机制。它使用几个异常处理宏,这些宏现在也被编译成C++异常,因此没有必要在新的代码中使用它们!在MFC编程中,异
常对象都是从CExcept派生。大多数MFC异常处理对象都是动态分配的,因此当它们被捕获时,必须被删除;而没有捕获的MFC异常由MFC本身在AfxCa-
llWndProc函数中捕获并删除。
因为C++异常不能处理硬件和操作系统异常,因此需要将结构异常转化为
C++异常。
如何将结构异常转化为C++异常
Visual C++ 允许你通过使用_set_se_translator函数将结构异常转化为C++异常。
#include <eh.h>
class CSEHException
{
public :
CSEHException( UINT code , PEXCEPTION_POINTERS pep )
{
m_exceptionCode = code ;
m_exceptionRecord = *pep->ExceptionRecord ;
m_context = *pep->ContextRecord ;
ASSERTE( m_exceptionCode == m_exceptionRecord.ExceptionCode );
}
operator unsigned int() { return m_exceptionCode ; }
UINT m_exceptionCode ;
EXCEPTION_RECORD m_exceptionRecord ;
CONTEXT m_context ;
} ;
// 结构化异常到C++异常转化器
void cdecl TranslateSEHtoCE( UINT code , PEXCEPTIONPOINTERS pep )
{
throw CSEHException( code , pep ) ;
}
int APIENTRY WinMain( ……)
{
// 安装异常转化器
setse_translator( TranslateSEHtoCE ) ;
}
注意,异常转化器在每个线程的基础上进行工作,因此你需要为每一个线程安装一个转化器。这种异常转化器有一个副作用,你会在输出窗口的Debug标签中看见两个异常跟踪消息:一个是为了原来的结构异常,另一个是为了转化后的C++异常。使用了异常转化器后,你就可以像捕获C++异常一样捕获结构异常。
异常相关的编译选项
先看下面的函数:
void TestBugException()
{
try{
int *pInt = 0 ;
*pInt = 42 ;
}
catch(…){
MessageBox(0,””,0,MB_OK);}}
显然,上面的代码将会产生一个结构化异常,而处理异常却是用C++的异常
机制,这个异常会不会被处理呢?答案是决定于编译环境,在VC的默认情况
下,在调试版本中处理异常,而在发布版中并不进行处理。对于VC而言,
C++异常只能由throw语句抛出,或者在调用的函数内有throw语句。任何其它
的代码都不能接收C++异常,因此调式器将认为在try语句内没有C++异常(
因为没有throw语句),因而在发布版里将不需要的异常处理代码除去,以使程序得到优化。
上面描述的异常被称为同步异常模型,由/GX编译选项设置,而且是VC6的默认设置。与之相对的是异步异常模型,其采取任何指令都会产生
异常的机制,异步异常模型由/EHA编译选项设置。即/EHA选项可以使C++异
常机制捕获结构化异常。
还有一个编译选项:/EHS,也是同步异常,但和/GX不同的是,/GX表示
假设 extern “C”的函数不会抛出C++异常。extern “C”函数一般是由C函数编写的,因此它们不会抛出C++异常,当然也有例外。
如果你的程序使用了异常机制,但没使用其中一个异常处理编译选项,编译时将会产生一个警告信息:warning C4530 。
让new 和malloc 抛出异常
在VC默认情况下,new和malloc对于错误不会抛出异常。你可以通过使用
_set_new_handler安装一个处理器,让new针对错误抛出异常。通过调用
_set_new_mode让malloc使用同一个处理器。
#include <new.h>
int NewHandler( size_t size )
{
throw exception(“xxxx”);
}
int main()
{
_set_new_handler( NewHandler ) ;
_set_new_mode(1);
}
_set_new_mode(1) 表示malloc要使用new处理器。
异常的性能
当抛出异常时,函数调用链将从此回溯搜索,寻找可以处理抛出的这类异常
的处理器。当然,如果没有找到合适的处理器,进程将结束。如果处理器没有找
到,调用栈将被释放,所有的自动(局部)变量也将释放,然后栈将被整理为异
常处理器的上下文相关设备。因此异常开销由维护一个异常处理器目录和一个活动的自动变量表(它需要额外的代码、内存,而且不论异常是否抛出,都会运行),
还得加上函数调用链的搜索、自动变量的解析和栈的调整(它只在抛出异常的时候需要执行)组成的。
在很少抛出异常的情况下使用异常的开销并不大,而且可能会提高性能。
看下面的代码:
// 没有使用异常,而是判断指针
int check( int *pInt1 , int *pInt2 , int *pInt3 )
{
if( pInt1!= 0 && pInt2 != 0 && pInt3 != 0 )
{
......
}
else
return –1 ;
}
// 使用异常,如果参数为NULL的几率很低 , 使用异常效率更高!
int check( int *pInt1 , int *pInt2 , int *pInt3 )
{
try{
...
}
catch(...)
{
return –1 ;
}
}
异常处理需要大量的额外操作,使得它并不适于经常运行的代码(比如循环中)。
更详细地说,catch块有一些开销,但是try块有很少的开销;因此只有在抛出异
常的时候才会有很多的异常操作开销。
什么时候抛出异常
首先说明一下什么时候适合使用返回值,
1、用于非错误的状态信息
2、用于大多数情况下可以随意忽略而不会出现问题的错误
3、用于更易出现在循环中的错误,因为异常的额外开销,所以为了更好的性能 ,使用返回值是一个更好的选择
4、用于中间语言模块中的错误,例如COM组件,必须使用返回值而不是异常。
抛出异常的时机应该是一个函数发现一个错误,这个错误能阻止程序正常的运行。当函数不能使用返回值时,如构造函数或重载的操作符‘=’等也要抛出异常。但是,应注意不能从析构函数中抛出异常,因为异常可以阻止delete的调用,这样就会有资源泄露:
delete pObject
相当于:
pObject->~CObject()
operator delete ( pObject )
因此析构函数中抛出异常会跳过operator delete的调用!
使用异常规范
处理异常的一问题是知道一个函数可以抛出哪一种类型的异常。函数抛出
的异常应该被认为接口协议的一部分,和它的参数和返回值一样。
C++提供了异常规范,看下面的函数原型:
Void NormalFunction() ;
Void NoThrowFunction() throw() ;
Void ThrowFunction() throw( Cexception ) ;
其中,NormalFunction 可以抛出任何异常,因为它没有异常规范,而NoThrow-
Function则不能抛出异常,这两个函数的异常规范看起来是截然相反的。最后,
ThrowFunction可以抛出任何从Cexption派生来的异常对象。
异常规范的问题:
1、异常规范不完整:如果抛出的异常不是从异常规范类派生来的,线程会调用unexpected , 它会默认地结束进程。为了创建一个完整的函数规范,你需要找到所有由这个函数直接抛出和所有这个函数调用的函数抛出的未处理的异常(如果这个函数内已处理了这些异常就不考虑)。
2、异常规范在编译时不会检查,如下面的代码在编译时不会出现警告:
void Funtion() throw() // 规范:不会抛出异常
{
throw CException ; // 但实际上有抛出异常
}
3、不能和模板混合,因为模板参数可以是任何类型的,你不能知道这种类型的成员函数可以抛出什么异常;
4、如果你使用异常异常(即catch可以捕获结构化异常),实际上任何函数都可以抛出一个转化后的结构异常。
1、非MFC的C++异常应该通过引用来捕获( catch( except &e ) )。使用引用捕
获异常不需要删除异常对象(因为使用引用的捕获的异常会在栈中传送), 而且它保留了多态性(因此你捕获的异常对象正是你抛出的异常对象)。使用指针捕获异常需要你删除对象。
2、MFC异常应该通过指针来捕获。因为它们从堆中分配,当你处理完异常之后,
你需要调用Delete成员函数,如下所示:
catch( CfileException *e )
{
e->Delete(); // 不要使用delete ,因为一些MFC异常作为静态对象创建
}
你不能使用省略捕获处理器捕获MFC异常,因为这会导致一个内存泄露。
http可以支持很多字符集中(除了头,头必须是ascii),数据部分你可以试这用utf8解码,也可以试试unicode
一般是utf8
C++添加外部库文件(lib):
Project->properties -> Configuration Properties -> VC++ Directories ->Library Directories
C++添加外部引入文件(Include)
Project->properties -> Configuration Properties ->C/C++ ->General ->Additional Include Directories
如果不想使用默认的预编译头文件,可以去掉
Project->properties -> Configuration Properties ->C/C++ -> Precompiled Header-> Precompiled Header ->Not Using Precompiled Headers
修改默认生成的exe文件名称
Project->properties -> Configuration Properties ->General ->Target Name 和Target Extension
设置clean的文件
Project->properties -> Configuration Properties ->General ->Extensions to Delete on Clean
设置兼容2008版本
Project->properties -> Configuration Properties ->General ->Platform Toolset 为 v90
Linker Tools Error LNK1266 . pgd file not found