GetMemory 函数的几种经典考法

71 篇文章 2 订阅
GetMemory 函数的几种经典考法
 
//NO.1:程序首先申请一个 char 类型的指针 str,并把 str 指向 NULL(即 str
里存的是 NULL 的地址,*str 为 NULL 中的值为0),调用函数的过程中做了如
下动作:1申请一个 char 类型的指针 p,2把 str 的内容 copy 到了 p 里(这是
参数传递过程中系统所做的),3为p指针申请了100个空间,4返回Test函数.最
后程序把字符串 hello world 拷贝到 str 指向的内存空间里.到这里错误出现了!
str 的空间始终为 NULL 而并没有实际的空间.深刻理解函数调用的第 2 步,将
不难发现问题所在!
void GetMemory(char *p)
{
   p = (char*)malloc(100);
}
void Test(void)
{
   char *str = NULL;
   GetMemory(str);
   strcpy(str, "hello world");
   printf(str);

实质:GetMemory(str)在调用时会生成一个_str与str指向同一个数,这是因为C语言中函数传递形参不改变实参的内容,但是指针指向的内容是相同的,因此可以用指针控制数据。题中的GetMemory(str),实质是对_str操作,并没有对str操作。函数结束后_str撤销,因此不会产生新的内存空间。str仍然是一个空指针。

//请问运行 Test 函数后会是什么样的结果?

分析:程序崩溃。因为GetMemory 并不能传递动态内存,Test 函数中的 str 一直都是 NULL。strcpy(str, "hello world");将使程序崩溃。



//NO.2:程序首先申请一个 char 类型的指针 str,并把 str 指向 NULL.调用函数
的过程中做了如下动作:1申请一数组 p[]并将其赋值为 hello world(数组的空
间大小为 12),2返回数组名 p 付给 str 指针(即返回了数组的首地址).那么
这样就可以打印出字符串"hello world"了么?当然是不能的!因为在函数调
用的时候漏掉了最后一步.也就是在第2步 return 数组名后,函数调用还要进
行一步操作,也就是释放内存空间.当一个函数被调用结束后它会释放掉它里面
所有的变量所占用的空间.所以数组空间被释放掉了,也就是说 str 所指向的内
容将不确定是什么东西.
char *GetMemory(void)
{
   char p[] = "hello world";
   return p;
}
void Test(void)
{  
   char *str = NULL;
   str = GetMemory();
   printf(str);

}

实质:函数调用以后,会释放函数内部变量空间的内容,因此GetMemory()以后内部数据全部被释放了,所以打印出来的数据,不是我们要求打印的数据,但是返回的指针指向的地址是一定的。

请问运行Test 函数会有什么样的结果?
分析:可能是乱码。因为GetMemory 返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原来的内容已经被清除,新内容不可知。


//NO.3:问题同 NO.1,正确答案为可以打印出 hello.但内存泄漏了!  
void GetMemory(char **p, int num)
{
   *p = (char*)malloc(num);
}
void Test(void)
{
   char *str = NULL;
   GetMemory(&str, 100);
   strcpy(str, "hello");
   printf(str);

}

因为在GetMemory()中使用了malloc申请内存,但是在最后却没有对申请的内存没有做任何的处理,因此可能导致内存的泄露,非常的危险。

请问运行Test 函数会有什么样的结果?
分析:
(1)能够输出hello
(2)内存泄漏


//NO.4:申请空间,拷贝字符串,释放空间.前三步操作都没有任何问题.到
if 语句里的判断条件开始出错了,因为一个指针被释放之后其内容并不是 NULL,
而是一个不确定的值.所以 if 语句永远都不能被执行.这也是著名的"野"指
针问题.所以我们在编写程序释放一个指针之后一定要人为的将指针付成
NULL.这样就会避免出现"野"指针的出现.有人说"野"指针很可怕,会带来
意想不到的错误.
void Test(void)
{
   char *str = (char*)malloc(100);
   strcpy(str, "hello");
   free(str);
   if (str != NULL)
   {
      strcpy(str, "world");
     printf(str);
   }

}

需要注意的是内存释放以后不一定是NULL,也可能是一个不一定的值,因此有可能是其他的各种值,这是我们应该注意的问题。释放以后的值就是野指针,我们需要对野指针进行控制,释放以后,令:str = NULL;就能避免野指针的问题。

请问运行Test 函数会有什么样的结果?
分析:
篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str);之后,str 成为野指针,if(str != NULL)语句不起作用。


//

//

void GetMemory1(char *p)
{
    p = (char *)malloc(100);
}
void Test1(void)  
{
    char *str = NULL;
    GetMemory1(str);  
    strcpy(str, "hello world");
    printf(str);
}
//str 一直是空,程序崩溃
char *GetMemory2(void)
{  
    char p[] = "hello world";
    return p;
}
void Test2(void)
{
    char *str = NULL;
    str = GetMemory2();  
    printf(str);
}
char *GetMemory3(void)
{  
     return "hello world";
}
void Test3(void)
{
    char *str = NULL;
    str = GetMemory3();  
    printf(str);
}
 
//Test3  中打印hello world ,因为返回常量区,而且并没有被修改过。Test2
中不一定能打印出hello world,因为指向的是栈。
 
void GetMemory4(char **p, int num)
{
    *p = (char *)malloc(num);
}
void Test4(void)
{
    char *str = NULL;
    GetMemory3(&str, 100);
    strcpy(str, "hello");  
    printf(str);  
}
//内存没释放
 
void Test5(void)
{
    char *str = (char *) malloc(100);
    strcpy(str, "hello");
    free(str);  
    if(str != NULL)
{
   strcpy(str, "world");  
   printf(str);
}
//str 为野指针,打印的结果不得而知
 
void Test6()
{
    char *str=(char *)malloc(100);
    strcpy(str, "hello");
    str+=6;
    free(str);
    if(str!=NULL)
    {
        strcpy(str, "world");
        printf(str);
    }
}
//VC 断言失败,运行错误
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值