C++低级错误
来源:互联网 发布:地图数据 编辑:程序博客网 时间:2024/06/05 00:25
1. 数组下标访问越界
2. 使用野指针
3. 内存拷贝忽略字符串结尾标志’\0’
4. 判断无符号数是否小于0
5. 循环变量数据类型太小
6. 循环体内改写循环变量
7. 混淆”==”与”=”
8. 函数局部变量或参数过大,堆栈溢出
9. 数据类型不一致,变量或参数赋值出错
10. 分支流程未释放动态申请的内存
代码案例:
1. 数组下标访问越界
(1)数组下标根据计算得出
i = a – b ;
array[i] = 0 ; //使用前应该检查i的合法性
(2)数组下标通过函数得出
void main()
{
int i, b[10];[1]
getIndex(&i);
b[i] = 0; //使用前应该检查i的合法性
}
(3)数组下标是循环变量
void main()
{
int i, max, b[10];
getMax(&max);
for (i = 0; i < max; i++) //使用前应该检查max的合法性
{
b[i] = 0;
}
}
2. 使用野指针
(1)使用未分配空间的指针
void func()
{
char *p;
if (NULL != p)
{
printf(“%s”, p);
}
}
(2)内存空间释放后指针未置Null,内存指针仍被继续使用
void* g_pBuf = NULL;
void ATM_CellRecv(U8 *pBuf,U32 ulLen)
{
g_pBuf = pBuf;//g_pBuf通过pBuf赋值指向内存区域
......
if ( NULL != pBuf )
{
free(pBuf);//只是释放了内存,而g_pBuf并没有置成NULL.
}
}
3. 内存拷贝忽略字符串结尾标志’\0’
void fun()
{
char dest[10];
char src[] = "0123456789";
memcpy(dest, src, sizeof(src));
}
4. 判断无符号数是否小于0
unsigned char c;
//c赋值为具体的循环次数
while(c-->=0)
{
//do something…
}
5. 循环变量数据类型太小
unsigned char c;
unsigned short s;
//do something
//s > 255
for (c = 0; c < s; c++)
{
//do something
}
6. 循环体内改写循环变量
unsigned long i;
for (i = 0; i < 1024; c++)
{
for (i = 0; i < 512; c++)
{
//do something
}
}
7. 混淆“=”与“==”
如下例子的循环判断条件中,将”==”误写成”=”,导致死循环。
Bool result = True;
while(result = True)
{
result = execFunc();
wait();
}
编程规范要求将常量写在等号左边(如“True==result”),确保编译时即可发现错误。
8. 函数局部变量或参数过大,堆栈溢出
void Function(void) {
char b[0x200000];
}
int main()
{
ret = function();
}
函数参数的输入、输出如果是一个比较大的结构,要用指针带入保存输入数据的内存地址,用指针带入保存输出的内存地址,不要直接用值传递的方式输入和输出。如果函数的较大的输入输出使用值传递方式,对函数堆栈处理有较大的开销。当数据接近或者大于堆栈空间的时候,就会出现堆栈溢出错误
如果是使用DOPRA平台,可以在v_configkernel.h文件中找到默认的栈大小
#define VOS_DEFAULT_STACK_SIZE 0x200000
9. 数据类型不一致,变量或参数赋值出错
short int x;
int y;
void *p ;
p=&x;
*(int*)p=y;
x只有两个字节的空间,而int需要4个字节的空间, 实际上己出问题了。还有一个例子,会导致入参被踩:
int func(short int s, int* pi)
{
…//do something
*pi = 0;
return 0;
}
int main(int argc, char* argv[])
{
short int x;
short int y;
int iRet;
…//do something
x = 1;
iRet = func(x, (int *)&y);
}
调用函数func后, x = 0。
10. 分支流程未释放动态申请的内存
void Function1(int nSize)
{
char* p= (char*)malloc(nSize);
if( !GetStringFrom(p, nSize) )
{
MessageBox(“Error”);
return;
}
…//using the string pointed by p;
free(p);
p = NULL;
}
当函数GetStringFrom()返回零的时候,指针p指向的内存就不会被释放。这是一种常见的发生内存泄漏的情形。程序在入口处分配内存,在出口处释放内存,但是c函数可以在任何地方退出,所以一旦有某个出口处没有释放应该释放的内存,就会发生内存泄漏。
内存分配方式有三种:
(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量,静态内存区。
(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc申请任意多少的内存,程序员自己负责在何时用free释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。应用程序一般使用malloc,realloc等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。
- C语言低级错误案例
- C语言必须杜绝的低级错误
- 低级错误
- 低级错误
- 低级错误!
- 低级错误
- 低级错误
- 低级错误
- 低级错误
- C和C++易出现的低级错误
- c语言中应该绝对避免一些的低级错误
- 比较低级的错误
- CSDN-低级错误
- 北青网也会犯低级错误!
- android 之低级错误
- hibernate 低级错误
- 低级错误最可怕
- MySql设置 低级错误!!
- spring mvc注解入门例子
- 流体力学学习笔记2-A unified particle model for fluid-solid interactions
- 在64位机器上安装toad
- java与堆栈
- 怎样实现JS滑动门在Firefox下的正常运行?
- C++低级错误
- Ubuntu 12.04 下安装ssh 服务遇到的问题以及总结
- 08-15 Sizeof与Strlen的区别与联系
- POJ 1703 Find them, Catch them
- Verilog实现多地址I2C Slave
- SAP MIRO时 发票数量大于收货数量
- UVaOJ 558 - Wormholes
- PHP中替换换行符的方法
- 学习Linux的七点忠告