一个迷惑的异常
BYTE AxjGetStopChgReason ( BYTE bpn)
{
BYTE bSotpReason;
BYTE ReasonNum = 52 ;
ReadItemEx ( BN0, bpn, 0xB885 , & bSotpReason) ;
for ( BYTE i = 0 ; i < ReasonNum; i++ )
{
if ( g_tStopReason[ i] . bClou == bSotpReason)
return g_tStopReason[ i] . bAXJ;
}
return 0 ;
}
BYTE ReasonNum = sizeof ( g_tStopReason) / sizeof ( g_tStopReason[ 0 ] ) ;
C中常见的与内存有关的错误
内存错误可能的后果
可能立刻报段错误,也可能保护故障,也可能长时间不出错( 只是运行结果不对) ,甚至还有可能没有影响,程序也正常运行,那是什么原理呢?
如下一段为通用的内存管理模式:
内核虚拟内存 进程相关的内核数据结构 如页表、task、mmu结构,内核栈等 每个进程一样 物理内存 内核代码和数据 用户栈 … … 共享库映射区 共享库如libc.so,每个库包含.data和.text区域 … … brk开始 运行时malloc分配的堆 未初始化的数据 .bss 已初始化的数据.data 0x400000开始 代码段.text
如果你的内存出错了,具体出错位置:
1 :地址定位到其他进程了,地址不是本进程的——segment error
2 :地址定位到内核去了————内存保护错误
3 :地址定位错了,但还在本进程中,只是指向了别的有用地址————这个后果不唯一,可能的后果包括:
a:引用的地址是本进程的一个堆空间的,那就会改变堆空间的地址的数据( 如果应用指针有修改的话)
b:引用的地址是本进程的一个栈空间,修改了栈空间的内容,
但无论怎样,引用内存不会有致命问题( 顶多引用数据不正确) ,修改内存可能会导致:
a:后续真正该内存的主人过来用的时候,引用地址错了,导致segment error或者其他逻辑错误
b:修改了地址的内容,后续程序运行过来的时候,数据被修改了,运行逻辑错误。
错误——间接引用坏指针
正常:scanf ( "%d" , & val) ;
错误:scanf ( "%d" , val) ; ————此时scanf将val解释为一个地址,
最好情况下,程序立即异常终止( 内存到了别的内存区) ,最糟糕情况下,val对应虚拟内存某个合法读/ 写区域,于是覆盖了这个内存,以此通常会运行相当长一段时间后造成灾难性、令人困惑的后果。
错误——读未初始化的内存
. bss内存一般被加载器初始化为0 ,但堆内存不是,常见错误就是假设对内存初始化为0.
int * testvec ( int * * ptra, int * x, int n)
{
int i, j;
int * ptrb = ( int * ) malloc ( n * sizeof ( int ) ) ;
for ( i= 0 ; i< n; i++ )
{
for ( j= 0 ; j< n; j++ )
ptrb[ i] += ptra[ i] [ j] * x[ j] ;
}
return y;
}
此事例中,不应该假设ptrb被初始化为0 ,应该显式初始化为0.
错误——允许栈缓冲区溢出
void bufoverflow ( )
{
char buf[ 32 ] ;
gets ( buf) ;
return ;
}
错误——价值指针和他们指向对象大小相同
int * * makArray1 ( int n, int m)
{
int i;
int * * A = ( int * * ) malloc ( n * sizeof ( int ) ) ;
for ( i= 0 ; i< n; i++ )
A[ i] = ( int * ) malloc ( m * sizeof ( int ) ) ;
return A;
}
错误——造成错位
int * * makArray2 ( int n, int m)
{
int i;
int * * A = ( int * * ) malloc ( n * sizeof ( int * ) ) ;
for ( i= 0 ; i<= n; i++ )
A[ i] = ( int * ) malloc ( m * sizeof ( int ) ) ;
return A;
}
错误——引用指针,而不是指针指向的对象
int * binheapdel ( int * * binheap, int * size)
{
int * packet = binheap[ 0 ] ;
binheap[ 0 ] = binheap[ * size - 1 ] ;
* size-- ;
heapify ( binheap, * size, 0 ) ;
return ( packet) ;
}
错误——误解指针运算
int * search ( int * p, int val)
{
while ( * p && * p!= val)
p += sizeof ( int ) ;
return p;
}
错误——引用不存在的位置
int *getptr()
{
int val=100;
return &val;
}
//返回的指针指向栈的局部变量,然后弹出栈帧,此时指针还是一个合法地址,但不是合法变量了,后续该帧帧被其他函数使用,此处返回的值如被修改就可能导致莫名修改,轻则异常,潜在灾难性后果啊
错误——引用空闲栈块中的数据
int * heaptest ( int n, int m)
{
int i;
int * x, * y;
x = ( int * ) malloc ( n * sizeof ( int ) ) ;
. . . . . .
free ( x) ;
y = ( int * ) malloc ( m * sizeof ( int ) ) ;
for ( i = 0 ; i < m; i++ )
y[ i] = x[ i] ++ ;
return y;
}
错误——引起内存泄漏
void leak ( int n)
{
int * x = ( int * ) malloc ( n * sizeof ( int ) ) ;
return ;
}