Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jul 29 2015 07:11
    日本語のC++チャットルームです。C++に関連する話題であればなんでも自由に投稿・質問してください。
  • Jul 29 2015 07:10
    日本語のC++チャットルームです。C に関連する話題であればなんでも自由に投稿・質問してください。
  • Jul 29 2015 07:09
    日本語のC チャットルームです。C に関連する話題であればなんでも自由に投稿・質問してください。
  • Jul 29 2015 07:07
    てすと from nyaocat
Cryolite
@Cryolite

初心者質問ですいません!

int main() {
  int *p = nullptr;
  *p = 42;
}

が undefined behavior を起こすかどうかを純粋に規格の文言だけから結論できますでしょうか?

Kohei Takahashi
@Flast

微妙にそれるけど明らかなものとしては、pointer to member typeに関してはn4296 [expr.mptr.oper]/6に

If the second operand is the null pointer to member value (4.11), the behavior is undefined.

ってあるので、これはUB

で、本題の方はちょっと怪しくて、

揚げ足を取るような読み方すると、まずn4296 [dcl.ref]/5に

A reference shall be initialized to refer to a valid object or function. [ Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior.

というのがあって、じゃぁreferって何ってなるとn4296 [expr.unary.op]/1には

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.

とあるので、nullptrの位置にvalid objectがないことを示せればなんとかUBに持ち込めそう

Kohei Takahashi
@Flast
n4296 [dcl.ref]/5にUBって書いてあるじゃんって指摘には、これはNoteなので規格の挙動に影響を与えられないっていうのがあって書いてあるのに残念
op->*op[]に関してはそれぞれop.*op*へのequivalenceであることが示されているので割愛
Kohei Takahashi
@Flast
.oO(*がmarkdownに食われるの何とかできないかな...
nyaocat
@nyaocat
規格書さらってみましたけど Flast さんが既に書いてる以上の関係ありそうな文言はみつけられず _(:3 」∠)_
*アスタリスクは 先に \ をいれてやればエスケープできるみたいですね。 *
This message was deleted
Kohei Takahashi
@Flast
恐らく、*nullptrはUBですよってなると、組み込みとかでfree standing env.してる時に、ほんとにHWのアドレス0にアクセスする必要があった時に規格違反のコンパイラを作らないといけなくなってしまうから、あくまでvalid objectという表現に抑えてあるのではと推測
nyaocat
@nyaocat
あれ、 null pointer が アドレス 0 だとは規定されてないのでは?アドレス 0 にアクセスしうるような環境ならば別の値を null ポインタとすればよいはず
Kohei Takahashi
@Flast

お、確かに、n4296 [conv.ptr]/1だと

A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t.
A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type
and is distinguishable from every other value of object pointer or function pointer type.

と書いてあるだけで確かにnull pointer valueが0であるとは規定していないな

じゃぁ陽にUBにしていない理由が別にあるのかな...
nyaocat
@nyaocat
void f(int*);
std::vector<int> vec;
f( &vec[0] );
で vec が empty の時に実装によっては null のデリファレンスを起こして UB になるのを防ぐためとか……?
C++11以降なら vector<T>::data() を使えばよいですけど、 C++03 だと data() がなくて &vec[0] とか &(*vec.begin()) とか書いてるコードも多かったでしょうし。
ignisan
@ignisan
この辺読んでたけど初心者だから難しかった http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
Cryolite
@Cryolite

おぉ! CWG issue 232 は見落としていました! ありがとうございます! 現在の方向性は, indirection は許容して lvalue-to-rvalue conversion の段階で U.B. にしよう,ということですか.だとすると,関連する疑問であった

class X {
  void f();
};

int main() {
  X *p = nullptr;
  p->f();
}

は X::f で this が指している empty lvalue に対して lvalue-to-rvalue conversion が走らない限り完全に規格に準拠した well-defined program (ということに将来的にはなりそう)ということですか.

Kazutoshi SATODA
@k-satoda

未定義動作の話と聞いて混ざりにきました。

@Cryolite 現状の規格では * 演算子の結果が有効なポインタについてしか規定されていないので、現状は未定義動作という結論になるかと思います。(ヌルポインタniの場合の動作について処理系に対してなんの制約も無い)

明記が無いことも含めて規格の不備であるのは CWG #232 のとおり間違いないと思います。

this != nullptr を前提とした最適化がすでにいくつかのコンパイラで行われているので、非 static なメンバ関数呼び出しはメンバアクセスと同様に未定義のままとなるべきだろうと思ってます。ここらへん、修正案では抜けてる感じ。

2005 年の Note を最後に CWG #232 の進展が無いのはおかしいだろうと思うので std-discussion に投げて話を進めたほうがいいと思うんですけど、そんなつもりは無いですか?(このチャットルームで規格文面の話をするのもどうかと思うので・・・。)

Kohei Takahashi
@Flast
ちょっと気になったので質問です http://melpon.org/wandbox/permlink/tXlwc27Gi0ZPfNFN
これってwell-defined or UBどっちかわかる方いますか?
(単純にPDF開くのだるいとも言う
arithmeticae
@marionette-of-u
こんにちは
Type Erasureってむつかしいですね。
https://gist.github.com/marionette-of-u/7daa71220358746dc634
void pointerからbase-derivedの型消去に書き直したいけどエンバグしそうで怖い
Kohei Takahashi
@Flast
@marionette-of-u taskmainに型が現れてしまっているのでTypeErasureで書き直したいということですか?
arithmeticae
@marionette-of-u
はい。それもあります。現状ではtemplate関数を噛ませることで前方宣言を回避してラップしてますが、利便性に欠けます。
あとここのクラスにあるワーキングエリアがvoid*なので、できれば継承関係を使うTypeErasureの方がC++としてベターかなと。
https://gist.github.com/marionette-of-u/7daa71220358746dc634#file-tasklist-hpp-L50
arithmeticae
@marionette-of-u
∀any_type, std::is_same<void_type, any_type>::value == false (∧ std::is_same<void_type, void_type>::value == false) となる予約語void_typeがほしい
iya,
使いどころがない!
Kohei Takahashi
@Flast
まずはじめにTypeErasure以前に、型が現れてる状態でstorage作ったりして自前でどうこうする必要はなくて、std::tupleとかにまずはtask列を投げ込めばalloc/deallocとかややこしいことしなくていいのではというのがあります
arithmeticae
@marionette-of-u
いや、Types and Programming Languagesに応用方法と導入の難易度がすべての基底クラスの導入難易度と比較されていたような
実はC++03の時代にboostとvirtual tableが嫌いで書いたものをC++>=11に移植したものです
Kohei Takahashi
@Flast
次に内容として、Task列をfor_eachとかでなめたいということだと思うので、それはBoost.Fusionとかに投げてしまうか、std::index_sequenceで展開するようにして、あとはそれをするfunctorをstd::functionに投げ込む様にすればよいかと
arithmeticae
@marionette-of-u
あとstd名前空間使うとsst::list<sst::nest<sst::task<...>, ss::list<...>>>みたいなネストを解析するときに空間内汚染すると思い増しえt
なるほど
update内でnestした型のupdateを呼び出すんですね
コンパイラはそれを別の型と認識するので最適化で展開されることが期待できる
Kohei Takahashi
@Flast
nestのところよく見てないですが、結局flattenにしてfor_eachするんですよね
arithmeticae
@marionette-of-u
はい。
Kohei Takahashi
@Flast
ならばやはりTypeErasureを自分で書くことが目的でない限り、std::functionとかに押し込んだほうが幸せになると思います
Nobuyuki Nishiyama
@tek-nishi
よろしく願いします!!
nyaocat
@nyaocat
よろしくお願いします!!!
nyaocat
@nyaocat
これ、どうして clang だと通るようになってるのかどなたかご存知だったりします? https://ask.fm/EzoeRyou/answers/133409745751
Wandbox でポチポチしてみたところ clang3.0 の頃から警告無しで std::array から std::tuple に入る
nyaocat
@nyaocat
clang が、というより libc++ が、なのかな
melpon
@melpon
libc++、確かに配列のための特殊化がありますねぇ… http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?revision=246408&view=markup#l114
Kazutoshi SATODA
@k-satoda
@nyaocat この動作についての質問と解答が本家の ML アーカイブで見つかりました。
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20140929/115709.html
2014/10/01 時点で "This extension has not been proposed for standardization." だそうです。
拡張ということですけど、デフォルトで有効になってるとけっこう知らずに依存しちゃいそうな気がします。
nyaocat
@nyaocat
おぉぉ!なるほど!そういう提案があったことはさっぱり知りませんでした!!ありがとうございます!
警告オプションつけても警告でないし、うっかり依存したコード書いてしまう危険性はありそうですねぇ