12个有趣的C语言问答(详解)(2)

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

注意:调用free()方法释放内存时,参数必须要么是NULL,要么是先前从malloc/calloc或者realloc返回的地址,不能将一次动态申请的内存的部分释放。

6 atexit()和_exit()

Q:以下代码中的atexit()方法并没有被调用,直到为什么吗?

#include <stdio.h>
#include <unistd.h>

void func(void)
{
    printf("\n Clean up function called \n");
}

int main(void)
{
    int i = 0;

atexit(func);
    for (; i < 0xFFFF; i++);
    _exit(0);
}

A:这是因为使用了 _exit() 方法。此方法并没有调用清除数据相关的方法,比如 atexit()等。exit和_exit都是用来正常终止一个进程的,主要区别是_exit会立刻进入内核,而exit先执行一些清除工作(包括执行各种终止处理程序,关闭所有标准I/O等,一旦关闭了IO,例如printf等函数就不会输出任何东西了),然后才进入内核。这两个函数会对父子进程有一定的影响,当用vfork创建子进程时,子进程会先在父进程的地址空间运行(这跟fork不一样),如果子进程调用了exit就会把父进程的IO给关掉。

7 void*与C结构体

Q:能够设计一个方法接受任意类型的参数然后返回整数?同时,是否有办法传递多个这样的参数?

A:一个能接受任意类型参数的方法像下面这个样子:

int func(void *ptr)

如果需要传递多个参数,那么我们可以传递包含这些参数的结构体。

8 *与++运算符

Q:以下代码将输出什么?为什么?

#include <stdio.h>
int main(void)
{
    char *ptr = "Linux";
    printf("\n [%c] \n", *ptr++);
    printf("\n [%c] \n", *ptr);
    return 0;
}

A:程序的输出结果如下:

[L]

[i]

因为++与 * 的优先级一样,所以 *ptr++ 将会从右向左操作。按照这个逻辑,ptr++ 会先执行然后执行*ptr。所以第一个结果是'L'。也因为 ++ 被执行了,所以下一个printf() 结果是'i'。

9 Making changes in code segment

Q:以下代码运行时一定会崩溃,你能说出原因吗?

1 #include <stdio.h>
2 int main(void)
3 {
4    char *ptr = "Linux";
5    *ptr = 'T';
6    printf("\n [%s] \n", ptr);
7
8    return 0;
9 }

A:这是因为字符串常量“Linux”是以只读的形式存储的,而通过*ptr='T'语句,此代码尝试更改只读内存存储的字符串内容,此操作当然行不通,所以才会导致崩溃。

10 Process that changes its own name

Q:你能否写一个程序,在它运行时修改它的名称?

A:以下的代码可以:

1 #include <stdio.h>
 2 #include <memory.h>
 3
 4 int main(int argc, char *argv[])
 5 {
 6    int i = 0;
 7    char buff[100];
 8
 9    memset(buff, 0, sizeof(buff));
10    strncpy(buff, argv[0], sizeof(buff));
11
12    memset(argv[0], 0, strlen(buff));
13    strncpy(argv[0], "NewName", 7);
14    //Simulate a wait. Check the process name at this point
15    for (; i < 0xFFFFFFFF; i++);
16
17    return 0;
18 }

可以通过下面的方法测试

$ gcc chname.c -o chname
$ ./chname &
[1] 4677
$ ps 4677
  PID TTY      STAT  TIME COMMAND
 4677 pts/11  R      0:08 NewName

11 局部变量的返回地址

Q:下面的代码有问题吗?如果有,如何修改?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ade0bac6d6ef972df1527c03a0df1632.html