免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1982 | 回复: 4
打印 上一主题 下一主题

[C] 读不懂,一段以多线程程序由于线程间冲突导致栈破坏的程序,求大神解答。。。。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-03-04 15:01 |只看该作者 |倒序浏览
  1. #include <sys/types.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <pthread.h>
  6. #include <errno.h>

  7. #define LOGFILE                "error.log"

  8. #define NR_DATA                64
  9. #define NR_QUEUE        32

  10. #define NR_REQ                64
  11. #define NR_RES                16

  12. #define SV_ST_REQ        1
  13. #define SV_ST_RES_OK        2
  14. #define SV_ST_RES_NG        3

  15. struct service {
  16.         int req[NR_DATA];
  17.         int res[NR_DATA];
  18.         int status;
  19. };

  20. struct service *queue[NR_QUEUE];
  21. int rqueue, wqueue, nr_queue;

  22. pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER;
  23. pthread_mutex_t mtx2 = PTHREAD_MUTEX_INITIALIZER;
  24. pthread_mutex_t mtx3 = PTHREAD_MUTEX_INITIALIZER;
  25. pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
  26. pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;

  27. FILE *logfile;

  28. void log_setup_strings(char *buf, const char *func)
  29. {
  30.         struct timeval now;

  31.         gettimeofday(&now, NULL);
  32.         sprintf(buf, "[%d.%06d]:%s\n", now.tv_sec, now.tv_usec, func);
  33. }

  34. void log_error(const char *func)
  35. {
  36.         char *logbuf;

  37.         logbuf = malloc(256);

  38.         usleep(100000);
  39.         log_setup_strings(logbuf, func);

  40.         pthread_mutex_lock(&mtx3);
  41.         fputs(logbuf, logfile);
  42.         fflush(logfile);
  43.         pthread_mutex_unlock(&mtx3);

  44.         free(logbuf);
  45. }

  46. int queue_service_req(struct service *sv)
  47. {
  48.         int ret = -1;

  49.         pthread_mutex_lock(&mtx1);

  50.         if (nr_queue >= NR_QUEUE)
  51.                 goto out;
  52.        
  53.         queue[wqueue] = sv;
  54.         nr_queue++;
  55.         wqueue++;
  56.         if (wqueue >= NR_QUEUE)
  57.                 wqueue = 0;

  58.         pthread_cond_signal(&cond1);
  59.         ret = 0;

  60. out:
  61.         pthread_mutex_unlock(&mtx1);
  62.         return ret;
  63. }

  64. struct service *deq_service_req(void)
  65. {
  66.         struct service *sv;

  67.         sv = NULL;
  68.         pthread_mutex_lock(&mtx1);

  69.         while (nr_queue <= 0)
  70.                 pthread_cond_wait(&cond1, &mtx1);

  71.         sv = queue[rqueue];
  72.         nr_queue--;
  73.         rqueue++;
  74.         if (rqueue >= NR_QUEUE)
  75.                 rqueue = 0;

  76.         pthread_mutex_unlock(&mtx1);

  77.         return sv;
  78. }

  79. int proc_req(void)
  80. {
  81.         struct service sv;
  82.         struct timeval now;
  83.         struct timespec timeout;
  84.         int i, ret;

  85.         sv.status = SV_ST_REQ;
  86.         for (i = 0; i < NR_DATA; i++)
  87.                 sv.req[i] = 0;

  88.         ret = queue_service_req(&sv);
  89.         if (ret == -1)
  90.                 return -1;

  91.         gettimeofday(&now, NULL);
  92.         timeout.tv_sec = now.tv_sec + 1;
  93.         timeout.tv_nsec = now.tv_usec * 1000;

  94.         pthread_mutex_lock(&mtx2);
  95.         ret = pthread_cond_timedwait(&cond2, &mtx2, &timeout);
  96.         pthread_mutex_unlock(&mtx2);

  97.         if (ret == ETIMEDOUT)
  98.                 return -1;
  99.        
  100.         if (sv.status == SV_ST_RES_OK)
  101.                 return 0;

  102.         return -1;
  103. }

  104. int proc_res(void)
  105. {
  106.         struct timeval now;
  107.         struct service *sv;
  108.         int i;

  109.         sv = deq_service_req();
  110.         if (!sv)
  111.                 return -1;

  112.         pthread_mutex_lock(&mtx2);

  113.         usleep(900000);

  114.         for (i = 0; i < NR_DATA; i++) {
  115.                 gettimeofday(&now, NULL);
  116.                 sv->res[i] = now.tv_usec;
  117.         }
  118.         sv->status = SV_ST_RES_OK;

  119.         pthread_mutex_unlock(&mtx2);

  120.         return 0;
  121. }

  122. void *th_req(void *p)
  123. {
  124.         for (;;) {
  125.                 if (proc_req() == -1)
  126.                         log_error("Request");
  127.                 usleep(100000);
  128.         }

  129.         return NULL;
  130. }

  131. void *th_res(void *p)
  132. {
  133.         for (;;) {
  134.                 if (proc_res() == -1)
  135.                         log_error("Response");
  136.                 usleep(100000);
  137.         }

  138.         return NULL;
  139. }

  140. int main(int argc, char **argv)
  141. {
  142.         pthread_t reqs[NR_REQ], resp[NR_RES];
  143.         int i;

  144.         /* error log init */
  145.         logfile = fopen(LOGFILE, "w");

  146.         for (i = 0; i < NR_RES; i++)
  147.                 pthread_create(&resp[i], NULL, th_res, NULL);

  148.         for (i = 0; i < NR_REQ; i++)
  149.                 pthread_create(&reqs[i], NULL, th_req, NULL);

  150.         for (;;)
  151.                 sleep(1);

  152.         fclose(logfile);

  153.         return 0;
  154. }
复制代码
gdb 的backtrace无法正确显示。

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
2 [报告]
发表于 2013-03-04 15:21 |只看该作者
106 int proc_req(void)
107 {
108     struct service sv;
109     struct timeval now;
110     struct timespec timeout;
111     int i, ret;
112
113     sv.status = SV_ST_REQ;
114     for (i = 0; i < NR_DATA; i++)
115         sv.req[i] = 0;
116
117     ret = queue_service_req(&sv);

sv是栈上的, 函数退了就没了, 所以出错了, 其他没仔细看.

论坛徽章:
0
3 [报告]
发表于 2013-03-04 15:30 |只看该作者
回复 2# linux_c_py_php


    求仔细看,这个程序把我绕晕了,看不太懂。。没有注释,最好能分析一下这个程序。

论坛徽章:
7
摩羯座
日期:2013-12-05 10:42:57辰龙
日期:2013-12-27 13:40:49亥猪
日期:2014-01-15 09:10:37天秤座
日期:2014-01-20 11:22:20辰龙
日期:2014-01-26 17:02:25午马
日期:2014-01-27 14:22:34水瓶座
日期:2014-02-19 09:36:40
4 [报告]
发表于 2013-03-04 15:59 |只看该作者
楼上大神说的对,truct service *queue[NR_QUEUE],这个地方你存的是指针,可你赋值的时候是一个局部变量的地址,函数退出的时候局部变量就被回收了,别的线程访问这个地址肯定有问题。


一个优秀的程序员是能把复杂的问题简单化,而不是把简单的问题复杂化。还是变量名起名一定要见名知意,像mtx1,mtx2,mtx3,谁会一直想着mtx1锁的是哪个对象。回复 3# dxxtl


   

论坛徽章:
0
5 [报告]
发表于 2013-03-04 16:07 |只看该作者
回复 4# kdkgod


    这个是debug hacks中的一段程序,没有注释,变量多又乱,所以我看晕了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP