Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RMagick, migrate to ImageMagick 7 #RubyKaigi #RubyKaigi2019

Watson
April 18, 2019

RMagick, migrate to ImageMagick 7 #RubyKaigi #RubyKaigi2019

Watson

April 18, 2019
Tweet

More Decks by Watson

Other Decks in Programming

Transcript

  1. "RMagick is an interface between the Ruby programming language and

    the ImageMagick image processing library."
  2. I want to use Ruby ... •Web programming •iOS programming

    •Image processing •Machine learning, etc
  3. I want to use Ruby ... •Web programming •iOS programming

    •Image processing •Machine learning, etc To meet crazy great people at Ruby World
  4. Windows •Ruby has some environments • MingW • MSWin •

    Cygwin • Windows Subsystem for Linux
  5. Windows •Ruby has some environments • MingW • MSWin •

    Cygwin • Windows Subsystem for Linux
  6. Case 1 VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) {

    Image *image, *new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); }
  7. VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,

    *new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory
  8. VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,

    *new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory Destroy memory
  9. VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,

    *new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory Destroy memory Raise exception with unexpected value
  10. VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,

    *new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory Destroy memory Raise exception with unexpected value Unreachable by exception
  11. Case 2 static VALUE has_attribute(VALUE self, MagickBooleanType....[snip]) { Image *image;

    ExceptionInfo *exception; MagickBooleanType r; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); CHECK_EXCEPTION() return r ? Qtrue : Qfalse; }
  12. static VALUE has_attribute(VALUE self, MagickBooleanType....[snip]) { Image *image; ExceptionInfo *exception;

    MagickBooleanType r; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); CHECK_EXCEPTION() return r ? Qtrue : Qfalse; } Case 2 Allocate memory
  13. static VALUE has_attribute(VALUE self, MagickBooleanType....[snip]) { Image *image; ExceptionInfo *exception;

    MagickBooleanType r; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); CHECK_EXCEPTION() return r ? Qtrue : Qfalse; } Case 2 Allocate memory Missing destroy
  14. Case 2: Missing destroy lead to Memory Leak image =

    Magick::Image.read('sample.png').first image.gray?
  15. Case 3: Memory Leak by incorrect API usage image =

    Magick::Image.read('sample.png').first image.sharpen_channel
  16. Plan 1: Split RMagick ver 4.x RMagick ver 3.x ver

    3.0 ver 3.1 ver 2.16.1 ImageMagick 7 ImageMagick 6