int foo(unsigned char c) {
int value = 2147483600;
value += c;
if (value < 2147483600)
bar();
return value;
}
但利用这个 UB 进行优化的编译器会认为,既然 x 不会是负数,那么 value < 2147483600 就永远不会发生,所以整个 if 语句以及后面的 bar() 调用将可以被忽略,变成:
int foo(unsigned char c) {
int value = 2147483600;
value += c;
return value;
}
这其实是一种很危险的做法,因为 C 语言可以跨越各种 CPU 架构编程,当年标准定义时,CPU 架构的差异比今天还大,在处理上面这类问题时,即便在今天,不同的架构结果并不一定相同,比如有的平台用补码表示负数,所以溢出了就会变成 -2147483648,而碰到反码或者原码表示负数的架构下,溢出了可能就变成 0 或者其它,所以一些事情根本就没法具体定义,必须留给具体编译器具体平台去处理。
Kernel object handles are process specific. That is, a process must either create the object or open an existing object to obtain a kernel object handle. The per-process limit on kernel handles is 2^24. However, handles are stored in the paged pool, so the actual number of handles you can create is based on available memory.
Each handle has an entry in an internally maintained table. Those entries contain the addresses of the resources, and the means to identify the resource type.
/*
* Even though sizeof(SOCKET) is 8, it's safe to cast it to int, because
* the value constitutes an index in per-process table of limited size
* and not a real pointer. And we also depend on fact that all processors
* Windows run on happen to be two's-complement, which allows to
* interchange INVALID_SOCKET and -1.
*/
# define socket(d,t,p) ((int)socket(d,t,p))
# define accept(s,f,l) ((int)accept(s,f,l))
所以 openssl 不论什么平台,都将套接字看作 int 来使用:
int SSL_set_fd(SSL *ssl, int fd);
int SSL_set_rfd(SSL *ssl, int fd);
int SSL_set_wfd(SSL *ssl, int fd);
Windows用久了,垃圾实在太多,还会莫名其妙挑出来BUG,我通常一年重装一次系统