[ruby-trunk - Bug #5896][Open] object representaion in rb_enc_vsprintf()

Issue #5896 has been reported by Nobuyoshi N…


Bug #5896: object representaion in rb_enc_vsprintf()

Author: Nobuyoshi N.
Status: Open
Priority: Normal
Assignee: Yukihiro M.
Category: core
Target version: 2.0.0
ruby -v: trunk

=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] 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

Issue #5896 has been updated by Motohiro KOSAKI.

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

\StringValue(v);
rb_raise(“%p”)

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

Bug #5896: object representaion in rb_enc_vsprintf()

Author: Nobuyoshi N.
Status: Open
Priority: Normal
Assignee: Yukihiro M.
Category: core
Target version: 2.0.0
ruby -v: trunk

=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

redmine$B$K%3%a%s%H=q$$$?$s$G$9$,!"(BML$B$HO"7H$5$l$F$J$$$h$&$K8+$($k$N$G(B
$B$3$A$i$K$bEj9F$7$H$-$^$9!#(B

$B7Y9p$K$D$$$F$O!"(Bgcc$B$N3HD%$G$9$7(BPRINTF_ARGS$B$rD|$a$k$N$I$&$G$9$+!)(B
$B3HD%$7$?;~E@$G(Bprintf$B=q<0$K9g$o$J$$$N$O$7$h$&$,$J$$$H;W$$$^$9!#(B


$BC.2H>;Li(B(Masaya TARUI)
No Tool,No Life.

2012$BG/(B1$B7n(B16$BF|(B22:00 Nobuyoshi N. [email protected]:

Issue #5896 has been updated by Nobuyoshi N…

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()

Author: Nobuyoshi N.
Status: Open
Priority: Normal
Assignee: Yukihiro M.
Category: core
Target version: 2.0.0
ruby -v: trunk

=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

Issue #5896 has been updated by Nobuyoshi N…

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


Feature #5896: object representation in rb_enc_vsprintf()

Author: Nobuyoshi N.
Status: Open
Priority: Normal
Assignee: Yukihiro M.
Category: core
Target version: 2.0.0

=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

Issue #5896 has been updated by Masaya T…

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

Feature #5896: object representaion in rb_enc_vsprintf()

Author: Nobuyoshi N.
Status: Open
Priority: Normal
Assignee: Yukihiro M.
Category: core
Target version: 2.0.0

=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