volatile

抽象类中的抽象方法(其前有abstract修饰)不能用private、static、synchronized、native访问修饰符修饰。原 因如下:抽象方法没有方法体,是用来被继承的,所以不能用private修饰;static修饰的方法可以通过类名来访问该方法(即该方法的方法体),抽 象方法用static修饰没有意义;使用synchronized关键字是为该方法加一个锁。。而如果该关键字修饰的方法是static方法。则使用的锁 就是class变量的锁。如果是修饰类方法。则用this变量锁。但是抽象类不能实例化对象,因为该方法不是在该抽象类中实现的。是在其子类实现的。所 以。锁应该归其子类所有。所以。抽象方法也就不能用synchronized关键字修饰了;native,这个东西本身就和abstract冲突,他们都 是方法的声明,只是一个吧方法实现移交给子类,另一个是移交给本地操作系统。

volatile相较与synchronized是一种较为轻量级的同步策略。
volatile不具有原子性

抽象类中的抽象方法(其前有abstract修饰)不能用private、static、synchronized、native访问修饰符修饰。原 因如下:抽象方法没有方法体,是用来被继承的,所以不能用private修饰;static修饰的方法可以通过类名来访问该方法(即该方法的方法体),抽 象方法用static修饰没有意义;使用synchronized关键字是为该方法加一个锁。。而如果该关键字修饰的方法是static方法。则使用的锁 就是class变量的锁。如果是修饰类方法。则用this变量锁。但是抽象类不能实例化对象,因为该方法不是在该抽象类中实现的。是在其子类实现的。所 以。锁应该归其子类所有。所以。抽象方法也就不能用synchronized关键字修饰了;native,这个东西本身就和abstract冲突,他们都 是方法的声明,只是一个吧方法实现移交给子类,另一个是移交给本地操作系统。

volatile相较与synchronized是一种较为轻量级的同步策略。
volatile不具有原子性

内存分区:
  1)栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  2)堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。
  3)全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 -程序结束后有系统释放。注意:全局区又可分为未初始化全局区:.bss段和初始化全局区:data段。
  4)常量区—常量字符串就是放在这里的。程序结束后由系统释放
  5)代码区—存放函数体的二进制代码。

malloc calloc
malloc和calloc差不多,区别是后者申请的内存都是被清零了的
calloc(numElements ,sizeOfElement);
malloc(numElements *sizeOfElement) ;


最优选择:使用ISO/IEC TR 24731-1定义的字符串操作函数的安全版本,如strcpy_s、strcat_s()、sprintf_s()、scanf_s()、gets_s() 等
缺点是,编译器对TR 24731的支持还不普遍。
次优选择:如果编译器还未支持TR 24731,可以使用带n的替代函数,如strncpy/strncat/snprintf。

char *strncpy(char *dest, const char *src, int n) 不自动添加'\0'
int snprintf(char *str, size_t size, const char *format, ...)会自动添加'\0'


void Compliant(const char *msg)
{
if (msg != NULL)
{
std::string buf = "Error: ";
buf += msg; //【修改】使用C++标准库代替C风格的字符串操作函数
std::cout << buf << std::endl;
}
}
c++中不推荐使用c风格的字符串,而是直接使用std::string类型字符串

多线程环境下,禁止std::cout与printf混用
printf与std::cout分别为标准c语言与C++中的函数,两者的缓冲区机制不同(printf无缓冲区,而std::cout有),而且对于标准输出的加锁时机也略有不同
二者存在微弱的时序差别,而多线程环境下,很多问题就是由于微弱的时序差别造成的。
所以两者的混用很容易带来不可预知的错误,常见的错误有打印输出的结果不符合预期,
而严重错误时甚至会导致内部缓存区溢出,导致crash。所以建议在代码中检查对于系统
标准打印输出的兼容性,一定要使用统一的打印输出方法,而对于C++程序,更推荐统一使用流输出方法,而不推荐使用C风格的代码。


下列代码使用了可能被编译器优化掉的语句。
void Noncompliant()
{
char pwd[128];
if (retrievePassword(pwd, sizeof(pwd)))
{
//............
}

memset(pwd, 0, sizeof(pwd)); //编译器优化可能会使该语句失效
}

某些编译器在优化时候不会执行它认为不会改变程序执行结果的代码,因此memset()操作会被优化掉。
void Compliant()
{
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd)))
{
/* checking of password, secure operations, etc */
}
#pragma optimize("", off) //【修改】禁用部分优化编译选项,确保pwd被处理
memset(pwd, 0, sizeof(pwd));
#pragma optimize("", on)
}
如果编译器支持#pragma指令,那么可以使用该指令指示编译器不要优化此处的操作。

 

非静态局部变量没有默认值。
全局变量默认值为0 或者null
静态局部变量默认值为0

程序的局部变量存在于(栈)中,全局变量存在于(静态区 )中,编译时已经分配好,动态申请数据存在于( 堆)中。
Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。 Stack空间有限,Heap是很大的自由存储区
C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行

posted @ 2018-04-02 17:11  牧 天  阅读(240)  评论(0)    收藏  举报