Feature #5896

object representation in rb_enc_vsprintf()

Added by Nobuyoshi Nakada over 3 years ago. Updated almost 3 years ago.

[ruby-dev:45135]
Status:Closed
Priority:Normal
Assignee:Yukihiro Matsumoto

Description

=begin
(({rb_enc_vsprintf()}))で(({VALUE}))を受け付けるようにする拡張です。

文字列化したオブジェクトを含むメッセージを組み立てる場合、
(({StringValueCStr()}))や(({RSTRING_PTR()}))で得られるポインタを(({snprintf()}))などに渡
すというのが定番ですが、これはエンコーディングが保存されない、最適化に
よって元の(({VALUE}))が消されてしまいdangling pointerになってしまう危険性があ
る、などの問題があります。後者は、とくに(({rb_raise()}))のように(({NORETURN}))な関
数に渡すときには、tail-call最適化のために(({RB_GC_GUARD}))があっても安全とは
限りません。前者については今のところほとんど無視されている状態です。

これらの問題を解消するため、(({rb_enc_vsprintf}))(およびこれを使う関数全般)を
(({VALUE}))自体を受けつけるように拡張すべきだと考えています。具体的な指定方法
としては、新しい変換指定子(%vなど)を追加することも考えましたが、gccは割
りと小賢しくチェックを入れてくれるので、警告がジャマになります。

小崎さんによると、Linux Kernelでも(({printk()}))に対する似たような要望は多かっ
たらしく、(({%p}))で始まる複数文字の変換指定子というものが導入されているそう
で、ソース[1]を見ると今ではが20個近くもあるようです。

[1] [[URL|http://lxr.free-electrons.com/source/lib/vsprintf.c#L1116]]

Rubyではオブジェクト自身が文字列化メソッドを持っているため、それを使っ
て変換するもの一つあれば充分です。なるべく被りそうにないものということ
で、(({"%lo\v"}))あたりでよいのではないかと思っています。

以下のコードは、例として((%error.c%))にある(({rb_invalid_str()}))を変更したものです。

void
rb_invalid_str(const char *str, const char *type)
{
VALUE s = rb_str_inspect(rb_str_new2(str));

  rb_raise(rb_eArgError, "invalid value for %s: %"PRIsVALUE, type, s);

}

=end

Associated revisions

Revision 35776
Added by Nobuyoshi Nakada almost 3 years ago

Feature #5896

  • vsnprintf.c (BSD_vfprintf): [EXPERIMENTAL] object representation in rb_enc_vsprintf(). [Feature #5896]

Revision 35776
Added by Nobuyoshi Nakada almost 3 years ago

Feature #5896

  • vsnprintf.c (BSD_vfprintf): [EXPERIMENTAL] object representation in rb_enc_vsprintf(). [Feature #5896]

Revision 35785
Added by Nobuyoshi Nakada almost 3 years ago

  • test/-ext-/test_printf.rb: tests for [Feature #5896].

Revision 35785
Added by Nobuyoshi Nakada almost 3 years ago

  • test/-ext-/test_printf.rb: tests for [Feature #5896].

History

#1 Updated by Motohiro KOSAKI over 3 years ago

基本的には賛成なのですが、PRIsVALUEはなくちゃダメ?

\StringValue(v);
rb_raise("%p")

と書くよりもコードが汚くなってしまうのは、せっかくのいい提案を殺してしまうような気がします

#2 Updated by Nobuyoshi Nakada over 3 years ago

Motohiro KOSAKI wrote:

基本的には賛成なのですが、PRIsVALUEはなくちゃダメ?

\StringValue(v);
rb_raise("%p")

と書くよりもコードが汚くなってしまうのは、せっかくのいい提案を殺してしまうような気がします

VALUEがunsigned longだったりunsigned long longだったりするので、できる
限り警告を避けようと思うとPRIsVALUEは避けようがないんですよねぇ。

ほとんど使われてそうにない%iのほうが%oよりいいかも、という気もしますが。

#3 Updated by Nobuyoshi Nakada over 3 years ago

  • Tracker changed from Bug to Feature

#4 Updated by Masaya Tarui about 3 years ago

警告については、gccの拡張ですしPRINTF_ARGSを諦めるのどうですか?
拡張した時点でprintf書式に合わないのはしようがないと思います。

#5 Updated by Masaya Tarui about 3 years ago

redmineにコメント書いたんですが、MLと連携されてないように見えるので
こちらにも投稿しときます。

警告については、gccの拡張ですしPRINTF_ARGSを諦めるのどうですか?
拡張した時点でprintf書式に合わないのはしようがないと思います。

--
樽家昌也(Masaya TARUI)
No Tool,No Life.

2012年1月16日22:00 Nobuyoshi Nakada nobu@ruby-lang.org:

Issue #5896 has been updated by Nobuyoshi Nakada.

Motohiro KOSAKI wrote:

基本的には賛成なのですが、PRIsVALUEはなくちゃダメ?

\StringValue(v);
rb_raise("%p")

と書くよりもコードが汚くなってしまうのは、せっかくのいい提案を殺してしまうような気がします

VALUEがunsigned longだったりunsigned long longだったりするので、できる
限り警告を避けようと思うとPRIsVALUEは避けようがないんですよねぇ。

ほとんど使われてそうにない%iのほうが%oよりいいかも、という気もしますが。


Bug #5896: object representaion in rb_enc_vsprintf()
https://bugs.ruby-lang.org/issues/5896

#6 Updated by Nobuyoshi Nakada about 3 years ago

  • Subject changed from object representaion in rb_enc_vsprintf() to object representation in rb_enc_vsprintf()

#7 Updated by Shyouhei Urabe about 3 years ago

  • Status changed from Open to Assigned

#8 Updated by Nobuyoshi Nakada almost 3 years ago

  • % Done changed from 0 to 100
  • Status changed from Assigned to Closed

This issue was solved with changeset r35776.
Nobuyoshi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


Feature #5896

  • vsnprintf.c (BSD_vfprintf): [EXPERIMENTAL] object representation in rb_enc_vsprintf(). [Feature #5896]

Also available in: Atom PDF