[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 901- 1001- 2ch.scのread.cgiへ]
Update time : 11/01 06:23 / Filesize : 300 KB / Number-of Response : 1022
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

Rust part11



1 名前:デフォルトの名無しさん mailto:sage [2021/06/17(木) 00:24:12.56 ID:NvYoNP9C.net]
公式
https://www.rust-lang.org/
https://blog.rust-lang.org/
https://github.com/rust-lang/rust

Web上の実行環境
https://play.rust-lang.org

日本語の情報
https://rust-jp.rs/

※Rustを学びたい人はまず最初に公式のThe Bookを読むこと
https://doc.rust-lang.org/book/

※C++との比較は専用スレへ
C++ vs Rust
https://mevius.5ch.net/test/read.cgi/tech/1619219089/

前スレ
Rust part10
https://mevius.5ch.net/test/read.cgi/tech/1617367084/

2 名前:デフォルトの名無しさん [2021/06/19(土) 01:15:49.18 ID:3FFA7ImF.net]
>>1 おつ

3 名前:デフォルトの名無しさん [2021/06/19(土) 01:20:06.41 ID:VXoz87sA.net]
>>1


4 名前:デフォルトの名無しさん [2021/06/19(土) 02:14:18.53 ID:tZhqlEYm.net]
勉強中でいまいちよくわかってないんだけどさ
よくRsutでメモリの扱いが安全になるとか言われてるけど、これって解放忘れを防いでくれるだけであって、オーバーフローを防いでくれるものではないわけ?
それとも登場する全ての型がオーバーフローしないような仕組み(スタックプロテクター以上の何か)があるの?

5 名前:デフォルトの名無しさん mailto:sage [2021/06/19(土) 03:26:44.04 ID:5peZoltk.net]
>>4
型のオーバーフローっていうのは算術オーバーフロー(桁あふれ)のことかな?
であればここを読むといいと思う
https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-overflow

6 名前:はちみつ餃子 mailto:sage [2021/06/19(土) 04:22:00.60 ID:/f53/cxR.net]


7 名前:スタックプロテクターの話題を出すってことは
バッファオーバーフロー (バッファオーバーラン) のことじゃないかな。

配列は大きさの情報を持っているし、
配列の一部の範囲を受け渡すときはポインタでなくスライスで扱うのが Rust の基本的な設計になってる。
ポインタと違ってスライスは範囲の情報を持っているのでチェック可能で、チェックする仕様になってるよ。
溢れたら panic する。
(もちろん unsafe な操作をしたらいくらでも危険な操作は出来る。)

絶対に溢れないことがコンパイル時に見抜ける場合であれば
チェックしないように最適化したりすることもあるし、
チェックする場合でも現代的な CPU ではほぼ確実に分岐予測が成功するから
処理速度が遅くなる分は十分に小さいとかいう話があったはず。
[]
[ここ壊れてます]

8 名前:デフォルトの名無しさん mailto:sage [2021/06/19(土) 09:47:40.12 ID:5peZoltk.net]
バッファオーバーフローのことなのか
Safe Rustでは基本的に発生しないが仕組みというより
unsafeなコードを書く人が要求された安全性を保証するという約束の上に成り立ってる

Rustの要求するメモリ安全性を保証するためには
unsafeなコードでポインタをdereferenceする前にout-of-boundsかどうかのチェックが必要

9 名前:デフォルトの名無しさん mailto:sage [2021/06/19(土) 14:15:48.54 ID:lGsmv2n4.net]
境界チェックなんて他の言語でもあるし、別にそこがRustの特別な強みではないんだよな
それよりは、

> これって解放忘れを防いでくれるだけであって

だけじゃなくて、use-after-freeとか、
思わぬ箇所でオブジェクトが変更されることによるデータ競合とか、
をコンパイル時にチェックできるのが強い

詳細はThe Book 4章に
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
日本語版はこっち
https://doc.rust-jp.rs/book-ja/ch04-02-references-and-borrowing.html

10 名前:デフォルトの名無しさん mailto:sage [2021/06/19(土) 15:41:11.20 ID:7Y2aa0wT.net]
解放忘れ(メモリーリーク)はRustは
保証してないのでは?



11 名前:デフォルトの名無しさん mailto:sage [2021/06/19(土) 16:32:09.25 ID:+A5T+Cz1.net]
Rc/Arc以外でメモリリークって起こるの?

12 名前:デフォルトの名無しさん mailto:sage [2021/06/19(土) 16:52:09.35 ID:5/JSw/kX.net]
Box::leakして返された参照を捨てるとメモリリーク起こせる

13 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 02:45:16.68 ID:O2AvtKTb.net]
最近勉強始めたんだが、正直ムズイ

特にwinapiのポインタ引数が(構造体のポインタではなく)DWORDで定義されてたりするので、
キャストするのが超絶面倒臭い
microsoftはcrate修正してほしい

まあ、rustというよりwinapiの問題なんだが……

14 名前:はちみつ餃子 mailto:sage [2021/06/20(日) 02:57:43.41 ID:h62I7Iw3.net]
わかる。
DWORD とポインタをカジュアルに同一視する API はまだマシなほうで、
Rust は文字列をスライスで扱うから単純にポインタに変換してもヌル終端されてないのがクソめんどい。
文字列を渡すとかすごく普通にあることなんで、それがこんなに面倒くさいの勘弁して欲しい。

15 名前:デフォルトの名無しさん [2021/06/20(日) 06:34:35.27 ID:9R7FlmLP.net]
普通に書いててwinapiとか使う機会ないと思うけどOS機能を直接触る必要のあるライブラリでも書いてるのかな?

16 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 15:00:11.94 ID:ZAMdhkls.net]
OS層に近いAPI全く使わないならrustやc++とかデメリットの方が多いような。

17 名前:デフォルトの名無しさん [2021/06/20(日) 16:38:08.85 ID:K2CzG+CP.net]
俺も最近Rust勉強してるんだけど、GC無しでのメモリ管理が最高に気持ちいい
何もかもRustで書きたくなる

18 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 17:33:03.51 ID:D+WmuL2+.net]
ワイは基本moveってところが気に入ってる
参照をもって回るんじゃなくて
実態をmoveで渡してmoveで返されるとき清々しいのを感じる

19 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 17:51:48.27 ID:BAitg4NO.net]
システムコールや低レベルなライブラリをいい感じに安全にラップしてくれるcrateが提供されてるのはrustの良いところ

20 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 19:32:30.59 ID:5UZIMOEC.net]
moveって最適化ビルドだと消えたりしてるのかな?



21 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 21:04:33.39 ID:BAitg4NO.net]
moveが消えるとは?
moveがコンパイルされた結果のmemcpyなどが消えることはある

22 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 22:37:40.54 ID:X7PAuK/l.net]
>>13
Rustのスライスは、ほぼPascal文字列だから、Cよりも古くから作法や
概念は存在している。
しかし、なぜCがPascal文字列ではなく0終端文字列にしたのかには
理由があって、文字列の途中(部分文字列)を扱わない場合においては効率が良いから。
0終端文字列の欠点は、部分文字列を扱おうとするととたんに面倒なことになること。
ただ、strcmpみたいなものを書いたり、字句解析を書いたりするときには、効率は良い。
字句解析では決定性オートマトンの理論がグラフ的(状態遷移図的)になっており、
Cの0終端文字列とはとても相性が良い。
そして、コンパイラの実行時間の大部分は、実測してみると、意外にも字句解析が占めている。
字句解析は単純ではあるが、量が多いので1クロックの差がものをいう世界である。
ただ、Pascal文字列(スライス)が字句解析でも有利に働く場面はあるにはあるが。
どちらの方式が一方的に優れているとはいえない。

23 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 22:45:58.47 ID:X7PAuK/l.net]
>>21
すまん。今調べたら、Pascal文字列は、配列の先頭に文字数が
入っている特殊な形式で、スライスとはまた違うものだった。
今まで誤解していたわ。
Pascal文字列はダメだわ、全く意味無し。

ただ、俺が言いたかったのは、Rustのスライス方式も古くから概念自体は存在し、
Win32APIでもGetTextExtentPoint32()なんかが、ポインタと、その後に続く
文字数の両方を指定する方式を取っている。
このやり方は、文字列の中に 0x00 を埋め込まなくても部分文字列を扱えて
便利は便利。もしこれを部分文字列の場所を少しずつ変えていくようなの場合に、
0終端文字列でやろうとすると、効率が悪くなる。
ただ、いつでもスライスの方が0終端文字列より効率が良いという訳ではない。
それが>>21で言いたかったこと。決定性や非決定性オートマトンの考え方で字句解析を
する際には、Cの0終端文字列はスライスより効率が良い。

24 名前:デフォルトの名無しさん mailto:sage [2021/06/20(日) 22:54:46.58 ID:D+WmuL2+.net]
読む価値無い文章をダラダラ書いちゃうのって
なんらかの障害なんやろな

25 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 00:08:08.49 ID:85An+spJ.net]
>>22
そのせいでPascal文字列は長さ255文字までに制限されてたのよな。

26 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 00:46:14.79 ID:PP3lMGGZ.net]
結論は、Rustがそんなにすばらしい言語とは到底思えないということだ。

27 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 02:03:12.76 ID:wnQSc3ge.net]
ええんやで

28 名前:デフォルトの名無しさん [2021/06/21(月) 03:36:25.54 ID:JQDu6zSa.net]
>>25 まぁ用途によるやろ
発展途上なところもあるし、そもそもRustが向いてないような用途もある

29 名前:デフォルトの名無しさん [2021/06/21(月) 07:39:35.72 ID:3uERIKtL.net]
>>13
様々な文字列処理をしたことがある人になら自明ですが
文字列を扱う場合は¥0終端よりもスライスのほうが圧倒的に有利です
例えば何段か深いディレクトリの絶対パスが与えられた時に各ディレクトリのリストを返す(つまりsprit)時
¥0終端方式だと元の文字列を書き換え破壊しない限りコピーが発生してしまいます
スライス方式だと書き換えもコピーも発生しません

これは正規表現によるパターンマッチングでも同じで¥0終端方式だと結果である部分文字列をコピーしなければ返せません
またHTMLやJSONなどの様々な構造データの解析結果でもそうです
JSON文字列を解析して内部構造化表現にする時もスライス方式ならば文字列のコピーが発生せずに済むわけです

30 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 08:53:58.31 ID:xiUkcw19.net]
>>28
>文字列を扱う場合は¥0終端よりもスライスのほうが圧倒的に有利です

有利だろうが何だろうが、APIや過去の資産を活用するのに面倒という事実は何も変わらないが



31 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 09:07:04.10 ID:WbPJLyAM.net]
そういやRustの std::ffi::OsString って¥0終端なんだっけ?

32 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 09:43:03.40 ID:ILFJsIgR.net]
>>30
違う
null terminatedはCString

33 名前:デフォルトの名無しさん [2021/06/21(月) 11:29:12.30 ID:+vRECSeH.net]
>>29 FFIのことを考えつつスライスの恩恵(境界チェックなど)も受けるなら今のRustの文字列に最後に\0を入れるようにしたらいいと思ったけどなんでしないんやろ
\0分の1バイトぐらい今のPCじゃ問題にならないはず

34 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 11:49:33.30 ID:hH2X9nxJ.net]
>>32
従来の &str (部分文字列) とnul終端文字列を区別しないといけないけど
型で区別しようとすると結局今のCStr/CStringと同じになるのでは
文字列は部分文字列含め全部Stringみたいにヒープアロケーションするなら良いけどさすがに効率が悪すぎる

35 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 12:03:56.90 ID:vy1X2bYf.net]
これps5は60fpsでます??

36 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 12:11:12.63 ID:743v8uRC.net]
Rust違いです
ってかゲームのほうのRustって個別スレ無いんだね

37 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 12:12:05.66 ID:oYpDc35T.net]
FFIが必要な箇所で
let cstr = std::ffi::CString::new(str);
すれば済む話だからね

Win32APIだと\0終端の2バイト文字も渡したりするからCStringでも使い勝手悪そう
let wcstr: Vec<u16> = std::ffi::CString::new(str).to_str().unwrap().encode_utf16().collect();
で動くかな(試してない)
こっちは自分で'\0'足す方が簡単かもしれない

38 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 12:43:27.64 ID:UE5kS0Iw.net]
>>28
気持ちは分かるし、実際、その例に挙がっているケースではそうなんだけど、
字句解析は、コンパイラ理論の状態遷移図に基いて行うと効率が良いが、
それは 0 終端文字列の方が効率が良い。

39 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 12:53:52.20 ID:UE5kS0Iw.net]
何度も言うが、全面的にスライスが良いならC言語でも0終端文字列をやめに
してしまえばいいのだが、そういう訳ではない。
>>28 に挙がっているようなケースで、自分も同じような気持ちになったことは有るが、
一方で 0終端文字列の方が効率が良い例も少なからず存在しているので全面的に
スライス方式に変えてしまうのは難しい。
一番単純な例を書けば、英大文字の部分だけを読み飛ばす場合、

(1) ptrが0終端文字列を挿している場合:
while ( *ptr >= 'A' && *ptr <= 'Z' ) ptr++;

(2) (ptr, len)でスライス文字列を表現している場合 :
int cnt = 0;
while ( cnt < len && *ptr >= 'A' && *ptr <= 'Z' ) {ptr++; cnt++;}

後者だと、cnt < len と cnt++; の部分が追加されて効率が落ちる。

40 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 13:02:34.21 ID:WbPJLyAM.net]
Linuxカーネル開発における「Rust」採用の動き、グーグルとISRGがさらなる後押し
https://japan.zdnet.com/article/35172646/

> Googleは、ウェブサーバーソフトウェアの「Apache HTTP Server」向けのモジュールをRustによるモジュールで置き換えるというISRGのプロジェクトも支援している。



41 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 13:11:18.52 ID:+4cAknZI.net]
windows apiを使ってメッセージダイアログボックスを表示するサンプルが載ってるサイト教えてください

42 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 13:25:05.28 ID:hH2X9nxJ.net]
>>38
今のcpuとコンパイラの最適化で両者にどれくらいの性能差があるか示したベンチマークなどある?

rustでも文字列末尾に0を差し込めば同じことはできるので、本当に速くなるなら最適化の手法として採用しても良いかもしれない

43 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 13:41:31.99 ID:G7rEBmCP.net]
>>41
試しに手元の環境で1GB分やってみたが1割くらい差があるね
コンパイラはgcc9
でもRustの文字列ってnull文字含むことができるんじゃなかったっけ?試したことないけど

44 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 13:52:57.02 ID:xiUkcw19.net]
>>40

use winapi::um::winuser::*;

fn main() {
let str: Vec<u16> = "Hello, world!".encode_utf16().chain(Some(0)).collect();
unsafe{
MessageBoxW(std::ptr::null_mut(), str.as_ptr() , str.as_ptr(), MB_OK);
}
}

45 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 14:00:39.66 ID:yyeRDQfZ.net]
設計判断ってのは常にトードオフの選択だからな
ヌル終端にすることで得られるものと失うものを天秤にかける必要がある

得られるものしか見ないやつは設計からは手を引け

46 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 14:01:15.31 ID:yyeRDQfZ.net]
トレードオフね
あー恥ずかし

47 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 14:13:19.21 ID:t12YpwM9.net]
ああトードオフは重要だよな

48 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 14:31:05.42 ID:ILFJsIgR.net]
>>38
ptrとlenが分かってるなら別途カウントアップしていかなくても
どの位置のptrまで読めばいいか最初に分かるんじゃない?

49 名前:デフォルトの名無しさん [2021/06/21(月) 14:45:15.77 ID:6c6Y8dXA.net]
Rustってなんでprintlnの後にビックリマークあるの?

50 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 14:51:45.48 ID:G7rEBmCP.net]
>>47
確かに。end_ptrとの比較で終了判定した場合は(1)と差はなかった
比較一個分くらいなら今どきのプロセッサの並列実行で
十分吸収できるということかな



51 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 14:58:01.41 ID:oYpDc35T.net]
>>48
printlnは関数じゃなくマクロだから
ちなみにマクロにしてる理由は引数の型と個数が不定だから

52 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 15:29:27.47 ID:+4cAknZI.net]
>>43
先輩ありがとうございます!

53 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 15:40:08.22 ID:WbPJLyAM.net]
そういや、可変長引数を直接書けないからRustはクソって言う人はまだ見た事ないな
あんまり使わないからかな?

54 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 16:23:01.35 ID:hH2X9nxJ.net]
>>42
文字列中にNULが含まれないことを前提とした最適化だから
NUL含む場合は使えないという制約はあるね
Cの文字列と同じ制約だから実用上あまり困らないんじゃないのかな知らんけど

55 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 16:29:47.09 ID:hH2X9nxJ.net]
>>52
Cで可変長引数使いたくなるのってprintf系関数以外なんかある?

56 名前:デフォルトの名無しさん [2021/06/21(月) 16:52:01.19 ID:xiUkcw19.net]
>>54
ない
標準関数ではprintfとscanfだけ

57 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 17:01:59.90 ID:UE5kS0Iw.net]
>>47
なるほど、こういうことかな:
(2)' (ptr, len)でスライス文字列を表現している場合 :
int btm = ptr + len;
while ( ptr < btm && *ptr >= 'A' && *ptr <= 'Z' ) {ptr++;}

>>49
差は少なくはなるが、無くなるわけではない。
ptr < btm という部分が残るから。整数比較命令と 条件jmp命令の
合計2命令はまだ(1)より多い。

58 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 17:23:50.71 ID:a6mPBEl9.net]
>>56
そりゃ命令数に差があるのは当然だけど
現代的なプロセッサの並列発行や分岐予測を考慮して
なおパフォーマンス差があるかを見たかっただけなので
そちらは実際測定して差を確認できた?

59 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 17:32:00.25 ID:xiUkcw19.net]
議論するのそこ?
むしろセキュリティ(バッファオーバーランの危険性)とパフォーマンスを秤にかけて
rustはセキュリティの方を採用したってだけじゃない?

パスカル文字列なんて昔からあったわけだし

60 名前:はちみつ餃子 mailto:sage [2021/06/21(月) 17:54:38.56 ID:5bV+3LP7.net]
>>52
どうしてもやりたければビルダーパターンでまとめてから渡すイディオムが確立してるから
そんなに不満にもならないんじゃない?



61 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 18:00:00.24 ID:W8eb/Sbg.net]
>>58
いや安全な方を選んだってのはそのとおりだと思うけど
理論上遅いはずってのを実際測るとそうでもなかったってのはよくある話で
そこが気になっただけ

62 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 18:49:34.95 ID:xiUkcw19.net]
>>60
rustが組み込みも視野に入れている以上、現代的なプロセッサは当てにできないと思う
8bitマイコンとかでrustが動くのかどうかはわからないけど

63 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 19:12:19.82 ID:Qd3Oxzyr.net]
>>61
別にRustはあらゆるアーキテクチャでのパフォーマンスを保証するつもりはないと思うけどね
実際測定してるのはTier1環境だけだろうし

64 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 21:14:54.92 ID:MXwcp+e6.net]
winapiクレートを使うことってもうなくね?
Microsoft公式のwindiwsクレートの方がよっぽど使いやすいよ

65 名前:デフォルトの名無しさん [2021/06/21(月) 21:47:08.31 ID:L+7FW+LR.net]
>>38
>(1) ptrが0終端文字列を挿している場合:
>while ( *ptr >= 'A' && *ptr <= 'Z' ) ptr++;

その場合でも、まず与えられたデータが0終端しているかどうかを確認する必要がありますよね。
データがどこから来るのかは、
ネット上の通信相手か
ディスク上のファイルか
メモリ上の他言語等APIかになりますが、
いずれも盲目的に信頼せずに処理する必要があります。

そして小さいデータならばどんな処理方法でも誤差になるのでしょうが、
大きなデータの場合は>>28のように元はJSONとかHTMLのように構造をもっており、
その解析結果である各一部分が対象文字列になります。
すると0終端させた方がわずかに速く扱える可能性があるからといって、元の大きなデータから毎回コピーして0終端文字列を作る場合と、
コピーをせずにスライスのまま部分文字列を扱う場合との、比較になるのでははいでしょうか?

66 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 22:00:11.19 ID:xiUkcw19.net]
>>64
>元の大きなデータから毎回コピーして0終端文字列を作る場合

どこからコピーの話が出た?

67 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 22:22:17.51 ID:oYpDc35T.net]
>>65
変更したくない文字列"あいうえおかきくけこ"から部分文字列"かき"を取り出す場合、
スライス式だと元の文字列の[5:7]の範囲という形で表現できるからコピー不要だけど
ナル終端式だと"く"が邪魔で"かき\0"にできないからどこかに"かき"のコピーが必要になる

って話が>>28に出てる

68 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 22:57:58.01 ID:xiUkcw19.net]
>>66
なるほど、理解した

69 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 22:58:56.43 ID:ILFJsIgR.net]
その比較は部分文字列をコピーするかスライスで表現するかの違いであって
0終端文字列のメリット・デメリットとは少し違うんじゃない?
0終端でも同じようにスライスを(ptr, len)で作ればコピーは不要

70 名前:デフォルトの名無しさん mailto:sage [2021/06/21(月) 23:46:42.70 ID:oYpDc35T.net]
>>68
> 0終端でも同じようにスライスを(ptr, len)で作ればコピーは不要

それをやってしまうとその部分文字列に対して0終端のメリットが効かなくなるわけで
コピーしないとメリットを得られないというのがデメリットになってる



71 名前:デフォルトの名無しさん [2021/06/22(火) 02:10:06.59 ID:JEO56Dr7.net]
つまり部分文字列を扱う場合は、コピーが発生する0終端方式が不利になりますね。
具体的にファイルパスからディレクトリ部分を得るとか、URLからホスト名を得るとか、元データを破壊したくない時は0終端方式だとコピーするしかないです。
つまり一貫してRustのように始点&長さ方式の方が、有利かつメモリ安全ではないでしょうか?

さらに文字列比較の場合も長さ方式よりも0終端方式が不利です。
これはCのmemcmpとstrcmpの比較に還元されますが、
memcmpは64bit比較やSIMD利用ができるからです。

72 名前:デフォルトの名無しさん [2021/06/22(火) 02:44:25.97 ID:fStlaCDg.net]
&strって3つの意味があると思うんだよね
1: 文字列リテラル
2: Stringの参照
3: 部分文字列
文字列リテラルとStringは終端にNULLを付けるようにして(今まで通りlenやcapは残す)、部分文字列は部分文字列を意味する別の型を作ればいいと思った
こうすることでRust側ではlenやcapを使い、C側ではNULL終端を利用できるという状態になる(Stringや&strをRustで使ってもCで使ってもゼロコスト)
もしNULL終端ではない部分文字列をCで使いたければStringに変換すれば使えるようになる(これはコストがかかるけどCの文字列も同じ問題を抱えてるので問題なし)

73 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 08:19:32.37 ID:7Ks2gqqv.net]
>>70
それやるには文字列がimmutableでなければならないから、それによって生じるスペースコストとどっちをとるかって話だな。
それにimmutableな文字列って、部分変更に相当する処理をする場合に逆にコピーが必要になるし。
どっちにしても一概に、コピー不要だからこっちが有利、みたいな話にはならんかと。

74 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 12:15:08.38 ID:UUxAOJV3.net]
rustで初心者がハマるポイントを初心者が紹介します

・所有権の概念が難しい
・何をするにしても外部ライブラリが必要(乱数生成など)
・ポインタが難しい

75 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 12:16:52.83 ID:hfO2UPRV.net]
・検索すると同名のゲームの話ばかり出てくる

76 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 12:26:02.44 ID:jOUHjhXv.net]
・static変数の扱いが面倒臭い

77 名前:デフォルトの名無しさん [2021/06/22(火) 12:52:20.13 ID:P9tLBTwV.net]
>>64
>その場合でも、まず与えられたデータが0終端しているかどうかを確認する必要がありますよね。
「0終端文字列」
というのは、必ず0終端されている文字列の事なので確認は不要。
それを明確にするために、C言語では、const char *pszText; のように、
psz という接頭辞をつける流儀がある。
psz = pointer to string ending with zero.
   「0で終端している文字列へのポインタ」
という意味。これは、単なる const char *ptr; とは意味が異なる。
char c = 'A';
const char *ptr = &c;  // 単なる文字へのポインタ。0終端されていない。
char szText[] = "Hello"; // 0終端文字列。0終端されている。
const char *pszText = szText; // 0終端文字列へのポインタ。0終端されている。

78 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 13:23:35.92 ID:D73AVe+6.net]
>>76
ファイルから読んだデータをpszHogeに格納するときにゼロ終端の要件満たしてるか確認する必要あるよねって話だぞ

79 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 13:25:24.28 ID:RVuteXyT.net]
>>74がマジで深刻すぎる
ついでに加藤純一っていうゲーム実況者とかとじゅんっていうRust/Scala使いがいるのも紛らわしい

80 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 13:35:53.88 ID:IhZgQU+B.net]
>>76
>というのは、必ず0終端されている文字列の事なので確認は不要。

という考えで脆弱性を量産してきたC言語の負の歴史を顧みて
Rustを始めとした新しい言語は異なる文字列表現を採用してるわけだ



81 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 14:06:03.07 ID:P9tLBTwV.net]
>>77
コンピュータの世界で「確認」とは、データの中を検査するという意味で
使われるが、そういうことは不要。
自分で末尾に 0 を書き込む必要があるだけ。

82 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 14:15:33.98 ID:3bNpX0tT.net]
そこで確認不要とか言ってるからユーザにヌル文字含んだ文字列渡されて死ぬのでは

83 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 14:51:42.58 ID:jOUHjhXv.net]
セキュアプログラムは面倒だからなー
数値のオーバーフローチェックとかみんなやらないでしょ?
アップキャストして値に結果を放り込んでチェックした後、
ダウンキャストするとか面倒すぎる

84 名前:デフォルトの名無しさん [2021/06/22(火) 15:18:09.96 ID:YfWe7YWP.net]
>>73
Cより面倒臭そうω

85 名前:デフォルトの名無しさん [2021/06/22(火) 15:19:46.85 ID:YfWe7YWP.net]
>>76
そこまで出鱈目な話初めて聴いたわ

86 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 15:22:37.78 ID:P9tLBTwV.net]
>>81
そういう外部からの入力に対するエラーチェックはするのは当然だが、
0終端文字列でやる場合には、ファイルのバイト数だけ読み込んで、
一番最後に 0 を書き込んでおくとそれ以上まで進むことはない。
途中の 0 に関しては スライス方式でも同じ問題が残る。
途中に 0 が有っても大丈夫な様に作るだけ。

87 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 15:24:47.81 ID:P9tLBTwV.net]
>>84
ちなみに、リアルワールドでは俺は名プログラマだと評価されているぞ。

88 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 15:27:25.45 ID:P9tLBTwV.net]
良いプログラムを作るための基本ポリシー:
・外部データと内部データは明確に分ける。
・外部データを内部データに入れる場合は、エラーチェックを徹底的にする。
・内部データに関しては、原則的には完全に正しいことを前提にしてプログラム
 して良い。ただし、プログラムのミスのための念のためのチェックはしても良い。

89 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 15:47:48.20 ID:cJZ3y9Eg.net]
>>87
3番目のチェックはアサーション(assert)だと思うけどあれはコードを読む人に背景の条件を明示する意味もあるね
逆にアサーション以外の余計なチェックはコードを読む人を混乱させる可能性がある

90 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 16:20:58.03 ID:N/B8oZfx.net]
ヌル終端はパンチカードが現役だった時代に数バイトケチった名残

互換性のためにサポートしなきゃいけないのは理解できるが
今の時代にヌル終端が優れてるとかそれをデフォルトにしろってのは控えめに言って頭おかしい



91 名前:デフォルトの名無しさん [2021/06/22(火) 16:22:09.51 ID:jOUHjhXv.net]
>>87
外部と内部の定義プリーズ

92 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 16:30:14.48 ID:P9tLBTwV.net]
>>90
外部でーたとしては、他にも有ると思うが、一例としては、

1. 他人が自由に書けるファイルから読み取ったばかりのデータ。
 (アプリケーション内部にリソースデータとして内蔵し、安全性が
 テスト済みであるようなファイルは内部データとみなしても良い場合も有る。)

2. 安全対策を徹底したいライブラリの場合は、ライブラリを使う側が関数に
 渡してきたテキストデータや引数の値。
 ただし、このようなものまで徹底的にチェックするとなれば遅くなるので、
 設計思想によっては、NO-CHECK、または、軽いチェックだけで済ましても良い。

3. OSの場合は、同様なものとして、APIを呼び出した側が渡してきたデータ。
 これは、安全性チェックは徹底して行う必要がある。

4. データベースソフトなどの場合も、2や3に準ずる。どこまで安全チェックするかは、
 使用目的や用途、設計思想による。

93 名前:デフォルトの名無しさん [2021/06/22(火) 16:34:27.28 ID:jOUHjhXv.net]
ちょっと緩くないか?

94 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 16:48:00.98 ID:FRtvqWA7.net]
信頼境界線の引き方は諸説あるだろ。

95 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 19:06:39.53 ID:R8WO8pxt.net]
一般に、アプリの外に置いてあるファイルはチェックした方が良いが、
その中でも、テキストファイルは、信頼置け無い事が多いのでチェックは必要。
アプリの外に置いてあっても、バイナリデータだと人が手書きすることはないため、
設計思想にもよるが、安全チェックはある程度省略しても良いと考える流儀もありえる。

96 名前:デフォルトの名無しさん mailto:sage [2021/06/22(火) 19:33:50.85 ID:D73AVe+6.net]
結局アプリケーションがどう使われるか次第でしょ
アプリケーション作成時の前提が利用シーンの増加により後から覆されるなんてことは良くあることだから
性能要件がない限り最初から安全側に倒しておくのが合理的

97 名前:デフォルトの名無しさん mailto:sage [2021/06/23(水) 11:02:20.62 ID:o/eJBU4s.net]
constデフォルトあたりの話ってgoto禁止論みたいになっている気がする
理由を理解していないがとりあえずそうしておけみたいな人を少なからず見かけるような

>>94
パーサーがガバガバで細工したセーブデータで乗っ取られるゲームのことか

98 名前:デフォルトの名無しさん [2021/06/23(水) 14:27:15.67 ID:LIFxwhU8.net]
>>95
MS製のリンカ(link.exe)の入力するlibraryファイル(*.lib)には、
ヘッダ部分にシンボルがアルファベット順にソートされたシンボルテーブル
が入っている。ソートされていることを前提にバイナリサーチが出来るので
シンボルを検索するのが高速になるとされる。バイナリサーチは、ソート
されているデータに対してのみ正しく検索できて、もしソートされていなければ
間違った結果になる。
しかし、link.exeが*.libを入力する時、ちゃんとシンボルテーブルのシンボル
がソートされたかどうかチェックしているかと言うと、定かではない。
だから、もし、サードパーティー製のツールが*.lib を作成した時、
ソートにミスがあったりすると、link.exeはundefined s

99 名前:ymbolエラーを出すか、
リンクには成功するが、実行段階でアプリが起動できなかったり途中でダウン
してしまうかも知れない。その様な場合、何が原因かは分からないであろうが、
多分、実際、検査はされてない。
[]
[ここ壊れてます]

100 名前:デフォルトの名無しさん mailto:sage [2021/06/23(水) 14:30:46.54 ID:LIFxwhU8.net]
>>97
実際は、サードパーティー製ツールも、ちゃんと*.libのヘッダのシンボルテーブルの
シンボルはソートしており、その部分にはバグはないので、それがソートされてない
*.libは基本的には存在しない。
ただし、*.libをバイナリエディタで開いて手作業で間違って変更したりすると
ソートされていないものが出来上がる。
それをlink.exeに入力しても、link.exeは、そのことに関してのエラーは出さない
だろう。








[ 続きを読む ] / [ 携帯版 ]

次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<300KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef