Linux(CentOS7) c语言编程, 多线程入栈出栈,错误:expected ‘while’ before ‘int’

发布时间 2023-04-06 21:43:25作者: 悟透

在Centos7里,编写多线程的入栈出栈时,出现这样错误提示:

图片版:

 文字版:

[root@CentOs7 05-xitongbiancheng]# gcc 05-24-01.pthread-cancel-pop-push.c -pthread
05-24-01.pthread-cancel-pop-push.c: 在函数‘func’中:
05-24-01.pthread-cancel-pop-push.c:47:1: 错误:expected ‘while’ before ‘int’
 int main(void)
 ^
05-24-01.pthread-cancel-pop-push.c:79:1: 错误:expected declaration or statement at end of input
 }
 ^
05-24-01.pthread-cancel-pop-push.c:79:1: 错误:expected declaration or statement at end of input

 

 

分析一: 看提示很明显,是语法错误,某个地方缺少“}”了,但是,进过仔细查看,括号都是成对出现的。

 

分析二: 用 grep 统计括号数量也是对的,如下图:

图片版:

 文字版:

[root@CentOs7 05-xitongbiancheng]# grep -c "(" 05-24-01.pthread-cancel-pop-push.c
24
[root@CentOs7 05-xitongbiancheng]# grep -c ")" 05-24-01.pthread-cancel-pop-push.c
24
[root@CentOs7 05-xitongbiancheng]# grep -c "{" 05-24-01.pthread-cancel-pop-push.c
5
[root@CentOs7 05-xitongbiancheng]# grep -c "}" 05-24-01.pthread-cancel-pop-push.c
5

 

分析三:有人会说是隐藏的乱码。

用 cat -e 命令,打印文本,看报错行,也没有什么乱码。

cat -e 05-24-01.pthread-cancel-pop-push.c

 

分析四:是不是某行结尾有什么多余的字符,比如 \t 制表符之类的。

结尾除了回车换行,每行结尾的 空格、制表符都删了。 

 

分析五: 代码之前编译运行都没问题,是加上 pthread_cleanup_push( push_func, p); 这段出现的报错。

注释掉 这行,就又正常了。但仔细看了代码,没有发现任何语法、拼写错误。

 

------》》》》  从出现问题时,是14点多,到16点,苦思冥想,没有解决方法,休息一下,眼睛疼

------》》》》  家务处理完后,21点又到电脑前,接续:

 

分析六: 突然解决

本来想放弃的,但是又翻了翻代码,突然想起,课程中说,入栈和出栈要在同一层代码成对出现。

注意看,

下面完整源码,第36行,pop 被注释掉了(当时写第30行 push 的那段代码时为了方便调试,就把 pop 的注释掉)

结果没想到给自己埋下了雷。

 

解决方法:就是把 第36行,pop 行取消注释,就可以正常编译成了

 

编译:

图片版:

 文字版:

gcc 05-24-01.pthread-cancel-pop-push.c -pthread

  加 -pthread 参数是因为,多线程用的不是系统的库,所以要加上,具体看 man 手册;

  在 ubuntu里 则用的是 -lpthread 参数,注意发行版差异这点。

 

 

 

-----------   以下是完整源码   ----------------

 1 /*  
 2  *  练习:
 3  *      创建多线程,新线程等待一会,并取消线程,同时设置入栈出栈,
 4  *      来保护数据。
 5  *  注意:
 6  *      在不同发行版的Linux(Ubuntu、CentOS)中,需要的头文件不一样
 7  *  Date:
 8  *      2023/04/06
 9  *
10  * */
11 
12 #include <stdio.h>
13 #include <pthread.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 void push_func( void *arg )
18 {
19     printf("压栈 push_func 函数执行\n");
20 }
21 
22 void *func(void *arg)
23 {
24     int *p = calloc(1, 4);
25     *p = 1024;
26 
27     // 收到线程取消请求,执行入栈(压栈)    
28     // 参数1:压栈要执行的指针函数
29     // 参数2:压栈要执行的指针函数参数
30     pthread_cleanup_push( push_func, p);
31 
32     printf("这里是 func 函数, ID: %ld\n", pthread_self() );
33     sleep(5);    // 模拟程序处理数据的耗时
34 
35     // 出栈
36     //pthread_cleanup_pop(0);
37 
38     // 5秒,没有收到取消线程请求,线程会主动退出,
39     // 并设置,退出值 1024 (数字当前是随意写的)    
40     //int *p = calloc(1, 4);
41     //*p = 1024;
42     pthread_exit( (void *)p );
43 }
44 
45 
46 int main(void)
47 {
48     // 创建新线程
49     pthread_t t_id = -1;
50     pthread_create( &t_id,    // 新线程ID 
51                     NULL,    // 线程属性
52                     func,     // 线程运行指针函数
53                     NULL);    // 线程运行指针函数的参数
54 
55     // 新线程创建后继续执行下面代码
56     printf("这里是 main 函数, ID: %ld\n", pthread_self() );
57 
58     // 取消线程请求
59     sleep(1);
60     printf("准备取消线程!\n");
61     sleep(0.5);  // 等待线程完全创建完,防止线程没有创建完,就取消。
62     pthread_cancel(t_id);
63     
64     // 取消线程后,看看能否再结合。(结果是不能结合)
65     int *retval;
66     int ret_tryjoin = pthread_tryjoin_np( t_id, (void *)&retval); // tryjoin 不阻塞,错误直接返回
67     if(ret_tryjoin)
68     {
69         fprintf(stderr, "线程被取消,结合失败!\n返回值:%s\n", strerror(ret_tryjoin) );
70     } 
71     else 
72     {
73         printf("线程结合,func 退出值:%d\n", *retval);
74     }
75 
76     return 0;
77 }

 

 

 

 

 

-