http://blog.youkuaiyun.com/tianmo2010/article/details/6785912
常见的 指针,内存操作问题
- void getMemory(char *p)
- {
- p = (char *)malloc(100);
- }
- int main()
- {
- char *str = NULL;
- getMemory(str);
- strcpy(str,"hello world.");
- printf("str = %s\n",str);
- }
传入中GetMemory( char *p )函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完 char *str = NULL; GetMemory( str ); 后的str仍然为NULL
- char* getMemory()
- {
- char p[] = "hello world";
- return p;
- }
- int main()
- {
- char *str = NULL;
- str = getMemory();
- printf("str = %s\n",str);
- }
char p[] = "hello world"; return p; 的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。
- void getMemory(char **p,int num)
- {
- *p = (char *)malloc(num);
- }
- int main()
- {
- char *str = NULL;
- getMemory(&str,100);
- strcpy(str,"hello world.");
- printf("str = %s\n",str);
- }
传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句 tiffanybracelets *p = (char *) malloc( num ); 后未判断内存是否申请成功,应加上:
if ( *p == NULL ) { ...//进行申请内存失败处理 }
- int main()
- {
- char *str = (char *)malloc(100);
- strcpy(str,"hello world.");
- printf("str = %s\n",str);
- free(str);
- }
在执行 char *str = (char *) malloc(100); 后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上: str = NULL;
关于指针应用的小结:(非常重要的几个知识点)
1. 每当写一个子函数时,如果函数的形式参数有指针类型时,应该首先判断其是否为空
2. 每当对一个指针变量申请动态存储空间后,应该立即判断其是否申请成功
3. 对应的指针变量,如果开始已经申请动态存储空间,在其使用完毕以后,我们应该立即将其空间释放,以免造成内存泄露
补充的问题:
找出下面几个函数的错误:
试题1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
/*
这个题目咋一看,没有任何错误, 给strcpy()函数传递的两个实参参数类型均能满足要求。 但是细心一看我们会发现这个函数存在越界问题,"0123456789"这个字符串 的长度为 strlen("0123456789") + 1 = 11 , 而很显然string[10],不可能存储这么大的空间。 通常在使用strcpy函数时一定要考虑源串、和目的串的大小问题。
*/
函数改成下面的形式可能会健壮一些:
int StrCpy(const char *source; char dest[])
{
if( NULL==source || NULL == dest || ( strlen(dest) < strlen(source) ) )
return 1; // 返回值=1 表示复制失败
else
strcpy(dest,source);
return 0; //返回值=0 表示复制成功
}
试题2::
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1 = 'a';
}
strcpy( string, str1 );
}
/*
这个题目考查了两个问题:
1、 数组的首地址是常量,不可以作为左值, 即str1是一个常量,
它代表整个数组的首地址。
2、 第二数组的引用需要用下标,除了初始化时可以int iArray[10]={1,2}
这样赋值外,在其他地方不可以批量给数组元素赋值。
3、 同时strcpy复制函数是针对具有'\0'的字符类型变量,因此这个函数赋
值同样存在赋值越界的情况。
*/
改成下面的方式估计会健壮一些:
void test2( )
{
char string[10],
str1[10] ;
for(int i=0; i<10; i++)
str1[i] = 'a';
str[9]='\0';
strcpy(string , str1);
}
试题3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
//试题3同样存在越界的可能性。如果strlen(str1)=10, 则实际上str1占用的空间是11个。
//strlen函数返回的长度没有计算末尾'\0'字符。 因此需要注意。
改为下面的方式可能会更健壮:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) < 10 && NULL != str1 )
strcpy( string, str1 );
}
试题4:
void GetMemory( char *p )
{
p = (char *) malloc( 100 );
}
void Test( void )
{
char *str = NULL;
GetMemory( str );
strcpy( str, "hello world" );
printf( str );
}
/*
首先这个题目存在内存泄露的问题和指针指向空地址问题
说说这个题目的存在的几个问题:
1、 在GetMemory函数里面, 没有对malloc函数返回值进行测试
if(NULL==p)
2、 在函数里面没有对指针p进行释放
free(p);
3、这里会有一个问题,在C语言中默认时按值传递的, 不是按照地址传递的。
在程序里面不能改变str的指向。
GetMemory(str);不能改变str的指向。
函数原型为:
void GetMemory(char *p); 定义的就是一个指针类型的参数。
4、在函数内部不能改变传值参数的值
*/
/*****************
malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。调用malloc函数时,
它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求
的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果
有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多
的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。于是,
malloc函数请求延时,并开始在空闲链上翻箱倒柜地检查各内存片段,对它们进行整理,将相邻的小空闲块合并成较大
的内存块。如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要
进行返回值的判断。
**************/
改成下面形式可能更健壮一些:
Void GetMemory(char **p)
{
char *temp;
if(NULL != (temp=(char *)malloc(1000)))
*p=temp;
free(temp);
}
试题5:
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
/* 其实怎么说呢这个题目的理解比上面一个题目来对简单, 但是通过这个题目和上面
的题目需要知道一个事实:
那就是函数内部声明的局部变量(static类型的除外,当然还有register的除外),这里指的
是auto类型的变量, 其内存空间是在系统为应用程序开辟的栈里面申请。
而malloc函数申请的空间则是从系统为应用程序开辟的堆里面申请。堆里面申请的不会自动释放,
而栈里面申请的会随着函数声明周期的结束而自动释放。
这个题目的错误之处在于没有理解局部变量的生命周期。
*/
改成下面的形式可能会更健壮:
char *getmemory(void)
{
char *p=NULL;
if(NULL !=(p=(char *)malloc(strlen("hello word")+1))
return p;
}
试题6://这个题目是正确的
void GetMemory( char **p, int num )
{
*p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( &str, 100 );
strcpy( str, "hello" );
printf( str );
}
/*
这个题目在第四个题目已经实现和论述,不再论述
指的一提的是:
传递&str值,并不能改变str的指向。
*/
试题7:
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
... //省略的其它语句
}
/*
这个题目比上面的更加简单, 它的问题就是没有对malloc函数的返回情况进行
检测,
如果 NULL=(char *)malloc(NUM) 那么strcpy函数将不会成功执行,