免费注册 查看新帖 |

Chinaunix

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

[C] 求教,ImageMagick多线程,程序崩溃 [复制链接]

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-11-05 11:39 |只看该作者 |倒序浏览
本帖最后由 lhd666 于 2016-11-05 11:57 编辑

我写了一段图片压缩的代码,这段代码在单线程的时候没发现异常,可一旦多线程运行,就会报段错误,接收到SIGSEGV信号。我使用gdb进行调试,每次where的时候,报错都不一样,可能是因为我不太会用gdb。只好贴上代码,希望大家帮我看看,是不是哪儿写的不对。这段代码运行的时候,依然会压缩出几张图片来。
操作系统:fedora25
gcc:6.2.1
ImageMagick:6.9.3
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <wand/magick_wand.h>

  5. static int image_compress(const char *infile, const char *outfile, size_t max)
  6. {
  7.         MagickBooleanType status;
  8.         MagickWand *wand;
  9.         int width, height;
  10.         int ret = -1;

  11.         MagickWandGenesis();
  12.         
  13.         wand = NewMagickWand();

  14.         status = MagickReadImage(wand, infile);
  15.         if (status == MagickFalse)
  16.                 goto out;

  17.         width = MagickGetImageWidth(wand);
  18.         height = MagickGetImageHeight(wand);

  19.         if (width <= max && height <= max) {
  20.                 ret = 1;
  21.                 goto out;
  22.         }

  23.         if (width > height) {
  24.                 height = height * max / width;
  25.                 if (height == 0)
  26.                         height = 1;
  27.                 width = max;
  28.         } else {
  29.                 width = width * max / height;
  30.                 if (width == 0)
  31.                         width = 1;
  32.                 height = max;
  33.         }

  34.         MagickResetIterator(wand);
  35.         while (MagickNextImage(wand) != MagickFalse)
  36.                 MagickResizeImage(wand, width, height, LanczosFilter, 1.0);

  37.         status = MagickWriteImages(wand, outfile, MagickTrue);
  38.         if (status == MagickFalse)
  39.                 goto out;
  40.         ret = 0;

  41. out:
  42.         DestroyMagickWand(wand);
  43.         MagickWandTerminus();
  44.         return ret;
  45. }

  46. void *thread_func(void *arg)
  47. {
  48.         const char *infile = arg;
  49.         char outfile[256];

  50.         for (int i = 0; i < 10; i++) {
  51.                 snprintf(outfile, sizeof(outfile),
  52.                          "%ld-%d", pthread_self(), i);
  53.                 image_compress(infile, outfile, 1024);
  54.         }

  55.         return NULL;
  56. }

  57. #define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))

  58. int main(int argc, char **argv)
  59. {
  60.         pthread_t tid[4];

  61.         if (argc != 2) {
  62.                 fprintf(stderr, "Useage: %s <input image filename>\n", argv[0]);
  63.                 exit(EXIT_FAILURE);
  64.         }

  65.         for (int i = 0; i < ARRAY_LENGTH(tid); i++)
  66.                 pthread_create(&tid[i], NULL, thread_func, argv[1]);

  67.         for (int i = 0; i < ARRAY_LENGTH(tid); i++)
  68.                 pthread_join(tid[i], NULL);

  69.         return 0;
  70. }
复制代码



论坛徽章:
12
2015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之同曦
日期:2017-03-17 19:13:162016科比退役纪念章
日期:2016-11-07 08:28:12luobin
日期:2016-06-17 17:46:36wusuopu
日期:2016-06-17 17:43:4515-16赛季CBA联赛之福建
日期:2016-01-14 12:49:22程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2015-06-08 22:20:00程序设计版块每日发帖之星
日期:2015-06-08 22:20:002015年亚洲杯之科威特
日期:2015-03-24 14:21:272015年迎新春徽章
日期:2015-03-04 09:57:092016科比退役纪念章
日期:2018-04-10 16:20:18
2 [报告]
发表于 2016-11-05 14:36 |只看该作者
多线程不需要用锁保护吗?

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
3 [报告]
发表于 2016-11-05 16:36 |只看该作者
本帖最后由 lhd666 于 2016-11-05 17:23 编辑

回复 2# VIP_fuck

嗯,我就是不知道它的函数库是不是线程安全的,如果不是,由于压缩非常耗时,有的图片甚至需要十多秒(在本机找的一些较大的图片,还没特意去找大图),加锁的话很难起到提升效率的效果,达不到预期目的,如果不是线程安全的话,暂时想到的只有fork()了。

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2016-11-07 10:17 |只看该作者
回复 1# lhd666

image_compress(infile, outfile, 1024)
看不出,用多线程有什么好处?把infile输出到多个outfile文件?但是也没对位置什么的做区分,不是重复工作吗?

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
5 [报告]
发表于 2016-11-07 15:36 |只看该作者
本帖最后由 lhd666 于 2016-11-07 15:44 编辑

回复 4# lxyscls

哦,是这样的,我这个只是个示例,实际应用的时候肯定是不同的infile,将这些infile分别进行压缩,而不是对同一个infile进行多次压缩,这里只是写代码时偷了点懒。只有image_compress()才是真正需要用到的代码,其它的相当于它的测试代码。

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
6 [报告]
发表于 2016-11-07 15:39 |只看该作者
本帖最后由 lhd666 于 2016-11-07 15:43 编辑

回复 4# lxyscls

我的测试代码里面没有使用任何全局变量,我猜测可能是ImageMagick的代码里使用了全局变量,导致多线程出问题,但我对它的库不熟,所以不太确定是不是自己代码忽略了什么步骤或者顺序不对之类的。

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
7 [报告]
发表于 2016-11-07 19:53 |只看该作者

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
8 [报告]
发表于 2016-11-07 20:39 |只看该作者
回复 7# MMMIX

谢谢!早知道我当初编程时直接就用多进程就好了 。

论坛徽章:
2
15-16赛季CBA联赛之天津
日期:2016-12-20 17:56:18CU十四周年纪念徽章
日期:2017-04-20 16:30:16
9 [报告]
发表于 2017-02-16 09:50 |只看该作者
还把内容补充到这儿,会比较方便。
ImageMagick本身是线程安全的,但是它底层调用的一些库并不是,例如当前的JPEG就不是线程安全。如果需要并行的话,建议还是用fork()。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP