A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 倾心莫若初见 中级黑马   /  2016-10-19 10:38  /  3376 人查看  /  0 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 倾心莫若初见 于 2016-12-27 10:57 编辑

一.  gets() 方法
Q:以下代码有个被隐藏住的问题,你能找到它吗?
A:这个不显眼的问题就是使用了 gets() 方法。此方法接受一个string类型参数,但是却没有检测此数值是否 有足够的空间来拷贝数据。所以这里我们一般用 fgets() 方法将来的更好。
#include<stdio.h>

int main(void)
{
   char buff[10];
   memset(buff,0,sizeof(buff));

   gets(buff);

   printf("\n The buffer entered is [%s]\n",buff);

   return 0;
}


二,strcpy() 方法
Q:密码防护是很基本的功能,看看能否搞定下面这段代码?

#include<stdio.h>

int main(int argc, char *argv[])
{
   int flag = 0;
   char passwd[10];

   memset(passwd,0,sizeof(passwd));

   strcpy(passwd, argv[1]);

   if(0 == strcmp("LinuxGeek", passwd))
    {
       flag = 1;
    }

   if(flag)
    {
       printf("\n Password cracked \n");
    }
   else
    {
       printf("\n Incorrect passwd \n");

    }
   return 0;
}



三,main() 方法的返回类型
Q:请问下面这段代码能否通过编译?如果能的话,那么这段代码中隐含什么问题吗?
#include<stdio.h>
void main(void)
{
    char *ptr =(char*)malloc(10);
    if(NULL == ptr)
    {
       printf("\n Malloc failed \n");
        return;
    }
    else
    {
        // Do someprocessing
        free(ptr);
    }
    return;
}
A:答案是代码能通过编译,但是会留下针对main()方法的返回类型的警告。main()方法的真正返回类型应该为’int’而非’void’。这是因为’int’返回类型能够让程序返回状态值。尤其是当这段程序作为其他应用的附属程序时这个状态值将更加重要。

四,内存泄露
Q:请问以下代码有内存泄露吗?
#include<stdio.h>

void main(void)
{
   char *ptr = (char*)malloc(10);

   if(NULL == ptr)
    {
       printf("\n Malloc failed \n");
       return;
    }
   else
    {
       // Do some processing
    }

   return;
}

A:好,虽然上面的代码没有对指针 ptr 进行内存释放,但实际上即使是程序结束也不会造成内存泄露,因为当程序结束时所有一开始被占据的内存就全部清空了。但如果上面这段代码是在 while 循环里面那将会造成严重的问题
Note: 如果你需要了解更多关于内存泄露的问题以及如何使用工具检测内存泄露,你可以参考这篇文章 Valgrind


五,free() 方法

Q:以下代码当用户输入’freeze’时会奔溃,而如果输入’zebra’则运行正常,这是为什么?

#include<stdio.h>

int main(int argc, char *argv[])
{
   char *ptr = (char*)malloc(10);

   if(NULL == ptr)
    {
       printf("\n Malloc failed \n");
       return -1;
    }
   else if(argc == 1)
    {
       printf("\n Usage  \n");
    }
   else
    {
       memset(ptr, 0, 10);

       strncpy(ptr, argv[1], 9);

       while(*ptr != 'z')
       {
           if(*ptr == '')
                break;
           else
                ptr++;
       }

       if(*ptr == 'z')
       {
           printf("\n String contains 'z'\n");
           // Do some more processing
       }

      free(ptr);
    }

   return 0;
}

A:问题的根源是因为代码在while循环中改变了 ptr 指针的地址。当输入为’zebra’时,while循环甚至在执行 第一遍前就结束了,所以free()释放的内存地址就是一开始malloc()分配的地址。但是当输入’freeze’时, ptr记录的地址在while循环中被更改,因为将会是错误的地址传递到free()方法中引起崩溃。


六,常量
Q:以下代码运行时一定会崩溃,你能说出原因吗?
#include<stdio.h>
int main(void)
{
    char *ptr ="Linux";
    *ptr = 'T';
    printf("\n[%s] \n", ptr);
    return 0;
}
A:这是因为,通过 *ptr= ‘T’,此行代码尝试更改只读内存存储的字符串’Linux’。此操作当然行不通所以才会造成崩溃。


七,运行是修改自己的名称
Q:你能否写一个程序在它运行时修改它的名称?
A:以下代码可以完成
#include<stdio.h>
int main(int argc, char *argv[])
{
    int i = 0;
    char buff[100];
   memset(buff,0,sizeof(buff));
    strncpy(buff,argv[0], sizeof(buff));
   memset(argv[0],0,strlen(buff));
   strncpy(argv[0], "NewName", 7);
    // Simulate await. Check the process
    // name at thispoint.
   for(;i<0xffffffff;i++);
    return 0;
}

八,局部变量的返回地址
Q:下面的代码有问题吗?如果有,如何修改?
#include<stdio.h>
int*inc(int val)
{
  int a = val;
  a++;
  return &a;
}
intmain(void)
{
    int a = 10;
    int *val = inc(a);
    printf("\n Incremented value is equalto [%d] \n", *val);
    return 0;
}

A:虽然上面的代码有时运行会很好,但是在方法 inc() 中有很严重的隐患。当inc()方法执行后,再次使用局部变量的地址就会造成不可估量的结果。解决之道就是传递变量a的地址给main()。


九,处理 printf() 参数
Q:以下代码输出请问是什么?
#include<stdio.h>

int main(void)
{
   int a = 10, b = 20, c = 30;

   printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2));

   return 0;
}

A:输出将是

110..40..60

这是因为参数都是从右向左处理的,然后打印出来却是从左向右。

精华推荐:
3分钟带你读懂C/C++学习路线
为什么来黑马程序员学C/C++? 稳做IT贵族人才!



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马