源代码:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
void waiting(),stop(),alarming();
int wait_mark;
main()
{
int p1,p2;
if(p1=fork()) /*创建子进程p1*/
{
if(p2=fork()) /*创建子进程p2*/
{
wait_mark=1;
signal(SIGINT,stop); /*接收到^c 信号,转stop*/
signal(SIGALRM,alarming);
waiting();
kill(p1,16); /*向p1 发软中断信号16*/
kill(p2,17); /*向p2 发软中断信号17*/
wait(0); /*同步*/
wait(0);
printf("parent process is killed!\n");
exit(0);
}
else
{
wait_mark=1;
signal(17,stop);
signal(SIGINT,SIG_IGN); /*忽略^c 信号*/
while(wait_mark!=0);
lockf(1,1,0);
printf("child process2 is killed by parent!\n");
lockf(1,0,0);
exit(0);
}
}
else
{
wait_mark=1;
signal(16,stop);
signal(SIGINT,SIG_IGN); /*忽略^c 信号*/
while(wait_mark!=0)
lockf(1,1,0);
printf("child process1 is killed by parent!\n");
lockf(1,0,0);
exit(0);
}
}
void waiting()
{
sleep(5);
if (wait_mark!=0)
kill(getpid(),SIGALRM);
}
void alarming()
{
wait_mark=0;
}
void stop()
{
wait_mark=0;
}
C++技术网会员解答:
感谢对C++技术网的信任和支持,下面来分析一下找到你这个问题和解决问题的过程。希望你能从这个过程中得到启发,学会找错误和解决错误的方法。
1.根据错误提示定位错误代码
根据你的错误提示,可以很清楚的知道出错代码在17、18、30、42行。所以你先可以看看这几行代码,看看他们的特点。
2.根据错误的描述信息,确定错误的类型
错误提示是类型转换错误,即从类型void(*)()到void (*)(int)的转换错误。如果你对于这个错误提示不清楚,我在这里解释下。这里需要了解函数名、函数指针的概念。我们知道这个确实是类型转换的问题,然而这是什么类型到什么类型的转换,确实有点懵逼了。原因在于函数名和函数指针用的少,才不懂了。
我们这样定义函数:
void test() { printf("hello www.cjjjs.com"); }我们知道这是定义了一个函数名叫做test的函数。那么test就是函数的名称了,以后我们就可以直接调用test即可,如:
test();这是我们非常熟悉的了。那么函数名test是什么鬼呢?在我们程序员眼里,test就是一个可以编写的一个写好的函数名,执行了函数就是执行了函数里面的代码。我们没有人会问,test是什么类型的呢?这也是学习函数学习的不深入的地方了。
函数名其实就是函数定义的代码的入口。代码会编译为一串计算机指令集合,存在一个地方(在内存的一个位置)。那么这个地方就得有一个地址,否则你怎么找到这个代码执行呢?那么这个就是我们知道的函数名。函数名就是函数代码的入口,所以我们执行test()也就是定位到函数体定义代码位置开始执行函数体内的代码。
我们一提到地址,就会和指针扯上关系。因为指针存储的就是地址。那么函数指针也就是存储函数定义代码的入口地址了。test就是这个函数入口地址了,对程序员来说是一个符号,对于计算机来说,会对应一个地址。这个地址会对应到一个数据类型里去,那就是函数指针了。因为我们计算机要操作这个存储在一个位置的函数代码,并不是时时刻刻都放在CPU里的,而是在内存中的,只有需要执行的时候,才会从内存中读取这个函数代码。所以,必然会用一个指针去临时存储这个函数的入口地址,然后根据指针存储的地址加载函数代码。
所以,这个地址要存入函数指针变量中,必然需要和函数指针的类型是一致的。也就是说,这个函数名是有类型的,也就是我们常说的函数类型了。那么函数的类型就是根据函数的参数和返回值确定的。
函数名可以理解为指针类型。所以函数的定义,其实也就定义了函数的类型,所以test函数的类型就是void (*)()。这不就是定义函数指针的语法吗,其实也是定义函数类型的方法。指针需要确定类型,就需要借助被指向的类型,所以指针的定义其实也就可以看出来函数本身类型的定义。
同理,下面的函数:
void test(int v)
{
printf("hello www.cjjjs.com");
}
test函数的类型就是void (*)(int)。所以根据错误提示的类型转换错误,那么就是这两个函数的转换错误了。函数转换怎么会错误呢?正常的调用的参数错误是提示错误参数类型错误,这里提示函数本身类型错误,那么说明这里是将函数名当做参数来使用了。
3.根据参数错误提示的位置来确定具体是什么参数
错误提示的位置是实参2,查看代码,也就是signal函数的第二个参数错误了,而且第二个参数是函数名称。我们看到第二个参数是stop和alarming两个函数。所以在根据第2点,也就是知道是stop和alarming两个函数的类型没有任何参数,signal函数的第二个参数的函数类型需要一个int参数。signal函数在做类型自动转换的时候,发现两个函数类型不兼容,故有了此错误提示。
通过错误代码定位,错误类型分析,再根据错误的参数位置,就可以很清晰的找到问题了。这是解决问题的基本方法,也是最有效的方法,希望以后勤加练习,以后会让调试效率大大提高。
那么找到了问题,就好解决问题了。我们只要将stop和alarming两个函数增加一个int参数即可。代码如下:
void alarming(int v)
{
wait_mark=0;
}
void stop(int v)
{
wait_mark=0;
}
参数的名称不重要,你可以取一个其他的参数名,两个函数没有用到参数,所以也可以省略参数名v。这样就不存在函数类型转换错误的问题了。
提问的原因分析:
1.没有基本的分析问题的方法,前文已经提供了基本方法,请多多练习。
2.对于函数名、函数指针、函数类型这一部分的知识理解不深,所以对错误提示的函数类型转换不是很懂,这是最大的障碍。所以建议加深对函数、函数指针的学习和练习。在构建高度灵活的代码时,函数指针经常会被用到,所以请提前学好,而不是为了考试哦。
C++技术网叮嘱:我们会尽可能多的提供学习方法、研究方法、分析方法和解决问题的方法思路,同时会指引学习的方向,希望助你更快的学到精髓。在学习和练习时要多动手多思考,基础要打扎实。如果遇到自己很难理解的问题,可以随时来在线提问,可以得到更全面细致的分析,让你从问题面前慢慢深入问题核心,而不是给你一个解决问题的答案,希望你从中学到真正的东西。