- 1 名前:デフォルトの名無しさん [2017/11/04(土) 16:33:35.07 ID:NYxCuvMY.net]
- エスケープシーケンスやWin32APIなどの環境依存なものもOK
そのような質問は必ず環境を書きましょう 半角空白やタブでのインデントはスレに貼ると無くなります コードを貼れる所 codepad.org/ https://ideone.com/ 前スレ 【初心者歓迎】C/C++室 Ver.101【環境依存OK】 https://mevius.5ch.net/test/read.cgi/tech/1500329247/
- 792 名前:デフォルトの名無しさん [2018/05/23(水) 19:24:44.84 ID:Au5e7VGg.net]
- 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』 AA6VB
- 793 名前:デフォルトの名無しさん mailto:sage [2018/05/24(木) 10:45:43.84 ID:cPlRxlDn.net]
- AA6VB
- 794 名前: mailto:sage [2018/05/24(木) 20:42:22.15 ID:dCOL2CYR.net]
- >>775
たしかに、そこをつく本を書けば売れるかもしれない そんな本に書くべきことは、他に何があるだろうか? ・qsort() の説明 ・アセンブリ言語とのリンク ・PEフォーマット …etc
- 795 名前:はちみつ餃子 mailto:sage [2018/05/24(木) 21:49:22.52 ID:jqqWnK8Z.net]
- >>775,780
江添氏が C++ の入門書で、言語以外の周辺事情もある程度カバーしたものを書こうとしてるみたいだぞ。 今は二の補数を説明すべきかどうかとか TWITTER でグダグダ言ってるから、 当たり前みたいで、しかし説明を省略されがちなことも含まれると思う。
- 796 名前:デフォルトの名無しさん mailto:sage [2018/05/24(木) 22:04:43.75 ID:hqF4m+Xg.net]
- シフトを使って多倍長計算とか、ZDDとか(クヌースの4巻だけど日本発)
- 797 名前:デフォルトの名無しさん mailto:sage [2018/05/24(木) 23:04:39.55 ID:agu/wXZc.net]
- 浮動小数点の誤差がらみとか、バッファオーバーフローでなんで脆弱になるのかとか、キリがなくなるぞ
- 798 名前:デフォルトの名無しさん mailto:sage [2018/05/25(金) 06:31:49.05 ID:ZdzP9wu5.net]
- コンパイルとリンクとロードの話とか。
ソースファイルからオブジェクトファイルに変換したときに どんな情報が残ってどんな情報が消えるか。 オブジェクトファイル群をリンクした段階でまだ確定せずに 実行時のロードで配置されるアドレスのこと、あたり。
- 799 名前:デフォルトの名無しさん [2018/05/31(木) 19:40:53.15 ID:xDJZQ821.net]
- ちょっとCと関係ないですが、コンピュータサイエンティストの人がよくMacを使っているのはなぜですか?
- 800 名前:デフォルトの名無しさん mailto:sage [2018/05/31(木) 19:48:19.66 ID:DFMmAXw3.net]
- しねばいいのに
- 801 名前: mailto:sage [2018/05/31(木) 20:29:52.32 ID:4k9lsrlf.net]
- >>781
二の補数はあたりまえに書いてもいいとおもうけれども、二の補数以外のものがあることを陽に記述する必要はないんじゃないかな…
- 802 名前: mailto:sage [2018/05/31(木) 20:30:39.27 ID:4k9lsrlf.net]
- >>785
Mac はお高いからな…
- 803 名前:デフォルトの名無しさん mailto:sage [2018/05/31(木) 22:34:17.78 ID:Dy3hGHo2.net]
- >>785
17"でお手頃価格なWindowsなNoteが他に無くてね HPとかDELLだと2.5kgとか
- 804 名前:デフォルトの名無しさん [2018/05/31(木) 22:37:50.13 ID:xDJZQ821.net]
- >>788-789
ありがとうございます。 >>789 使い勝手がいいとかそういうことはないですか?
- 805 名前:デフォルトの名無しさん mailto:sage [2018/05/31(木) 22:42:46.81 ID:Dy3hGHo2.net]
- 当時は無かったな。
MSのセミナーとかもmac+windows多かったよ
- 806 名前:デフォルトの名無しさん [2018/06/02(土) 18:09:00.04 ID:YEAzW6Zk.net]
- ヘッダーファイルについて質問なのです。
ヘッダーファイル内で、 ostream というのを使っているのですが、 #include <iostream>をヘッダーファイル内に記述していません。 エラーが出るだろうと思いつつ、ビルドしてみたらエラーが出ませんでした。 これはどういうからくりでしょうか?
- 807 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 18:23:14.65 ID:tlq/OxaF.net]
- ヘッダファイルの中じゃなくostreamを使っている
- 808 名前:|訳単位(cppファイル)の中で最低1回include iostreamされてればOK []
- [ここ壊れてます]
- 809 名前:はちみつ餃子 mailto:sage [2018/06/02(土) 18:25:58.96 ID:LSJtd55X.net]
- >>792
他のヘッダファイルで include してて間接的に読み込んでいることになってるってのが、一番ありそうかなぁ。
- 810 名前:デフォルトの名無しさん [2018/06/02(土) 18:30:00.66 ID:YEAzW6Zk.net]
- >>793
ありがとうございました。 ↓のファイルをビルドするとエラーが出るのですが、何が原因かよく分かりません。 フレンド関数関連だと思います。フレンド関数については全く知らないので、真似して 作っただけです。 Vec.h codepad.org/3ROYH1yq Vec.cpp codepad.org/f3eSheBS
- 811 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 18:30:45.89 ID:YEAzW6Zk.net]
- >>794
ありがとうございました。 もしかしてヘッダーファイルのみをビルドしてもオブジェクトファイルはできないんですか?
- 812 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 18:34:39.57 ID:YEAzW6Zk.net]
- >>795
ある本に書いてあるコードでは、 Vec.h と Vec.cpp のようには分かれていないため、 自分で分けたのですが、エラーになってしまいました。
- 813 名前:デフォルトの名無しさん [2018/06/02(土) 18:46:23.02 ID:RQ4rJlvL.net]
- 定義があればヘッダだけでもオブジェクトファイルに実装はできますよ。
- 814 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 18:50:06.69 ID:YEAzW6Zk.net]
- >>798
Vec.h codepad.org/3ROYH1yq 上のVec.hの最初の方の #include <iostream> #include <cassert> 削除してもビルドエラーが出ません。 プロジェクトにはVec.hしかない状態でビルドしました。
- 815 名前:はちみつ餃子 mailto:sage [2018/06/02(土) 18:55:56.26 ID:LSJtd55X.net]
- >>799
テンプレートのエラーはテンプレートが実体化するときに出ると思うよ。 だから、テンプレートを使ってないなら、エラーがあってもコンパイル自体は出来たりする。
- 816 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 19:00:50.14 ID:YEAzW6Zk.net]
- >>800
ありがとうございました。 あともう一つ質問なのですが、ロベールの本に、 「関数を実体化するには呼び出したところからその実装が見える必要があります。」 「つまり、関数テンプレートは宣言と実装をヘッダファイルとソースファイルに分離して 書くことはできず、すべてヘッダファイルで実装する必要があるのです。」 と書いてあります。 クラステンプレートについては同様の記述がないのですが、 クラステンプレートについても宣言と実装をヘッダファイルとソースファイルに分離して 書くことはできず、すべてヘッダファイルで実装する必要がありますか?
- 817 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 19:00:59.43 ID:uqsytqRM.net]
- >>795
このへんの問題かな? https://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/friend_%E9%96%A2%E6%95%B0%E3%81%AE%E7%94%9F%E6%88%90(Making_New_Friends)
- 818 名前:はちみつ餃子 mailto:sage [2018/06/02(土) 19:06:46.84 ID:LSJtd55X.net]
- >>801
Yes。 テンプレートはヘッダファイルに書く必要がある。 同じ実体 (テンプレート引数も同じなテンプレート) はリンク時に統合されるので、 最終的な実行ファイルに複数の実体があったりはしない。
- 819 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 19:21:25.63 ID:YEAzW6Zk.net]
- >>802
ありがとうございました。 ちょっと理解できないと思うので、あきらめて codepad.org/ABfo8I3a としたところビルドできました。 ありがとうございました。
- 820 名前:デフォルトの名無しさん mailto:sage [2018/06/02(土) 19:22:03.75 ID:YEAzW6Zk.net]
- >>803
ありがとうございました。
- 821 名前:デフォルトの名無しさん [2018/06/03(日) 17:10:25.43 ID:XweloLai.net]
- ヘッダファイルについて質問です。
assert() が使いたいため、「List2.h」内に、以下のように書いたとします。 #pragma once #include "List.h" #include <cassert> 実は、「List.h」内にも#include <cassert>が書いてあります。 ヘッダファイルにはすべて#pragma onceを書いているので多重インクルードについて 問題はないと思います。 そこで質問なのですが、「List2.h」内で assert() を使っているため、自分としては、 必要ありませんが、「List2.h」内にも#include <cassert>を書いた方が分かりやす いのではないかと思いました。 既にインクルードされていてもあえて、#include <> を書くという人はいるのでしょうか? それとも、既にインクルードされていることに気付いている場合には、できるだけ #include <> は書かないほうがいいのでしょうか?
- 822 名前: mailto:sage [2018/06/03(日) 17:20:14.25 ID:5RsKIUxf.net]
- >>806
すでにインクルードされているかどうかは書いているときにはわからない、から書いとく ただヘッダは分割コンパイルにおいて共用するデータだけを書いておくものだから ヘッダ List.h に #include <cassert> が含まれているのは、一見、疑問だと思った しかしテンプレート関数に assert() が
- 823 名前:入る場合があるのだから、こういったこともあり得るのかもしれないが、まだ私は体験していない… []
- [ここ壊れてます]
- 824 名前:デフォルトの名無しさん mailto:sage [2018/06/03(日) 17:34:16.61 ID:XweloLai.net]
- >>807
ありがとうございます。 >ただヘッダは分割コンパイルにおいて共用するデータだけを書いておくものだから >ヘッダ List.h に #include <cassert> が含まれているのは、一見、疑問だと思った ここのところがよく理解できないのですが、 List.h にテンプレートクラス List<T> が書いてあって、 List2.h には List<T> を継承したクラス List2<T> が書いてあります。 そして、List.h, List2.h の両方で assert() を使っています。
- 825 名前: mailto:sage [2018/06/03(日) 17:36:57.15 ID:5RsKIUxf.net]
- >>808
うんうん、なるほど テンプレートに assert() が含まれているのならば、ヘッダに #include <cassert> が入るのも止むを得ないです
- 826 名前:デフォルトの名無しさん mailto:sage [2018/06/03(日) 17:47:06.72 ID:XweloLai.net]
- >>809
ありがとうございました。 また質問で申し訳ないのですが、今度は、全く違う質問になります。 一方向リスト用のセルである Cell<T> というクラスを作りました。 Cell<T> のメンバ変数は、 T data Cell<T> *next です。 List<T> には、一方向リストの先頭のセルを指すメンバ変数 Cell<T> *head およびリストに挿入したり、 リストから削除したり、リストのサイズを返したりする様々なメンバ関数があります。 List<T> は一方向リストでしたが、List2<T> は双方向リストにしたいとします。 オブジェクト指向プログラミングでは再利用が重要ということなので、 新たに、双方向リスト用のセルを作るのではなく、 Cell<T> を継承して Cell2<T> というクラスを作ることにします。 Cell2<T> には新たにメンバ変数 Cell<T> *prev を追加します。 List2<T> のほうも List<T> と共通で使えるメンバ関数があるため、再利用したいとします。その場合、気持ちとしては、 List<T> のメンバ変数 Cell<T> *head は無効にして、新たに、 Cell2<T> *head と Cell2<T> *tail をメンバ変数に したいです。 そして、Cell2<T> に対しても使えるメンバ関数はそのまま使い、双方向リストにしたことにより、より効率的に実装できる メンバ関数については、オーバーライドしたいです。 上記のようなことをどうやって実現したらよいのか分からないのですが、可能でしょうか? 可能だとして、こういうやり方は非推奨でしょうか?
- 827 名前:デフォルトの名無しさん mailto:sage [2018/06/03(日) 20:55:43.49 ID:E53R3BDh.net]
- 一方向・双方向リストの、ソースコードを見た方が速い
繰り返しを表す、C++ iterator みたいな、 抽象クラス・インターフェースでも使っているのだろう
- 828 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 08:19:48.74 ID:DAGyu3MW.net]
- 再利用など考えず
一から好きなように双方向リストを作れ >オブジェクト指向プログラミングでは再利用が重要 は幻想 この場合で言ったらまったく逆で もともと何か双方向リストがあって、継承して機能制限をして一方向リストに仕立て上げるなら分かるが 一方向リストを継承して双方向リストにするなどイカれてる
- 829 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 09:50:25.37 ID:3BCLNr2e.net]
- >>810
一方向リストと双方向リストでどれ程共通的な処理があるのか知らんけどCellBase<T>に共通的な処理を定義してそれからCell<T>とCell2<T>を継承させるのが普通じゃね?
- 830 名前:はちみつ餃子 mailto:sage [2018/06/04(月) 13:04:55.31 ID:zKvF3SpI.net]
- どうだろう。
総合的な判断が必要という前提はあるけども、 継承が妥当なときの基準のひとつに「is a 関係であるか?」ってのがあるよね。 XはYの一種であると言えるときはXはYを継承していい。 双方向リストは一方向リストの一種であるかというと、まあ Yes って呼んでいいんじゃないの。 ただ、それで楽に使いまわしが出来るかというとそうでもないこともあるので、楽なように作ればいいよ。 練習でやるのなら、使いまわしは置いてそれぞれを作ってみた上で、 共通な部分を探してデザインしなおしてみるというのもいいんじゃないかな。 クラス定義自体は継承関係を持たずにトレイトの方で性質を定義したりとかいったことも今どきはよくやるし、 将来的にコンセプトが入ったらそっちが主流になるかもしれん。
- 831 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 13:18:55.79 ID:K9p9OoRg.net]
- >>812
もともと何か一方向リストがあって、継承して機能追加をして双方向リストに仕立て上げる これはダメなん?継承は機能追加ダメなん?
- 832 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 13:19:07.80 ID:e7JLMPXe.net]
- >>811
ありがとうございました。 >>812 本を見ると再利用が重要と強調されているので、拘ってしまいました。 ありがとうございました。 >>813 ありがとうございました。
- 833 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 13:20:24.25 ID:e7JLMPXe.net]
- >>814
ありがとうございました。
- 834 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 13:43:52.15 ID:3BCLNr2e.net]
- >>815
>>812はだいぶイカれてるから触らないで
- 835 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 14:30:56.26 ID:YRbUwbvV.net]
- >>810
単方向リストから双方向リストを派生させると、内部構造が違うから相違を埋めるのに面倒臭い事になる 派生した双方向リストから単方向リスト内部のノード列にアクセスできたとしても 単方向リストの状態は単方向でノードが繋がっているのだから双方向リストからどうこうはできない 結局の所、双方向用のノードを単方向用ノードにアップキャストしないと格納できないし、取り出すにはダウンキャストしないといけない もし何とかして単方向リストに双方向用のノードを双方向に数珠繋ぎ出来たら、そのリストはもう双方向リストだよ あと、insert()の問題もある、std::forward_listの持つinsert_after()が何故そうなのかは構造的に一目瞭然でしょ 厳密に言えば、std::forward_listはコンテナ要件を満たしていないしな 単方向も双方向もLinked Listとして構造的に似ているが効率的に見ても構造的に見ても別のデータ構造だよ is-aの関係ですら無いし、再利用ってのはhas-aの関係を考えるべきで、継承は再利用するためのものではないよ 例えば、皆、std::stringをhas-aで利用するよね、std::stackはstd::vectorやstd::listなどのアダプタだよね
- 836 名前:デフォルトの名無しさん mailto:sage [2018/06/04(月) 16:46:27.38 ID:OAwYb5Pt.net]
- 自分の勉強用だったら、継承した双方向リストクラス作ってみて
「やっぱ普通に作った方が簡単にできたな」って経験をするのもいいと思う よく「オブジェクト指向はこうだから」って言葉にこだわって面倒くさいことしてる人いるけど プログラムの基本としては「わかりやすさ」「シンプルさ」こそこだわった方がいいと思うから 将来拡張予定がないプログラムなんかだと無駄な継承しない方がいい
- 837 名前: mailto:sage [2018/06/04(月) 19:05:36.84 ID:gbEnuF2j.net]
- キーワード「継承」もずいぶんと評価が落ちたものですねえ…
- 838 名前:はちみつ餃子 mailto:sage [2018/06/05(火) 02:58:20.15 ID:l2agtc6/.net]
- C++ からクラスが無くなることは無いだろうが、
構成の仕方の流行はだいぶん変わってて、 コンセプトが入ったら一気に再編されるかもしれない。 クラスの継承ってそんなに万能じゃないよ。
- 839 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 12:11:26.28 ID:ucySJasT.net]
- ま、そういうことです
単方向リストを継承して双方向リストにするのは悪手 やってみるまでもなくわかるだろJK 結局ほぼすべてのメソッドを上書きしないといけないから意味ない しかも一から双方向リストを書いた方が分かりやすいし速い
- 840 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 12:24:14.11 ID:ucySJasT.net]
- この場合、どうしても手抜きしたかったら
大は小を兼ねるの考えで、双方向リストのみを作って 単方向リストを使う場面でも双方向リストを使えばよい それがベストだろうというアンサーがちらついてるからこそ、余計に 単方向リストを継承して双方向リストってのが悪手に見えるんよなぁ 余談だけどC++には std::list っていう双方向リストがあるけど単方向リストは提供されてないし 単方向リストなどその程度の扱い、必要ない
- 841 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 15:11:28.97 ID:5kytDI4t.net]
- >>824
>余談だけどC++には std::list っていう双方向リストがあるけど単方向リストは提供されてないし std::forward_list など無かった
- 842 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 18:07:41.59 ID:9YbuVUhL.net]
- >>824
いやあ、単方向リストはそれはそれで使い道はあると思うよ 大体、キャッシュに載り易くメモリ効率も良いstd::vectorで十分だけど 挿入操作を多用するならstd::listやstd::forward_listの方が良いよね std::forward_listは、std::listよりも要素N個 x ポインタサイズ分のメモリ消費量を抑えられるし イテレータを使ってO(1)で連続してpush_back()みたいなことも出来る、pop_back()みたいなことはO(1)で出来ないけどね 必要性を問うよりも、その特徴を理解して適切に効率的に使うことが大事なんじゃないかな まあ、std::mapやstd::setは使うのを躊躇するけどな O(log n)で値を取り出せて、イテレータでソートされた要素に順次アクセス可能を売りとするけど、メモリ効率が悪すぎる 他の言語のそれらが大体ハッシュテーブルで実装されているのを見るに連想コンテナはunordered系で十分な気もする
- 843 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 19:32:54.16 ID:ucySJasT.net]
- 言葉が足りなくて申し訳ない
俺もリンクリストを使うことは有るけど、大概切迫していてカリカリカスタマイズしたいときに使うものだから 汎用のテンプレートのリンクリストを使ったためしがない 一方向リストなら、なおのこと使わない
- 844 名前:デフォルトの名無しさん [2018/06/06(水) 20:16:30.41 ID:rNkLMN6z.net]
- 単方向リストを継承して双方向リストを作ることは無いと思うけど、コンポジットすることはあると思う。
ゼロコストの原則の視点に立つと、単方向リストを実装に流用して、双方向リストを作成するのもあり。
- 845 名前:デフォルトの名無しさん [2018/06/06(水) 20:30:07.38 ID:sZLPzbQ0.net]
- STLのコンテナにstd::unique_ptr突っ込むと、カスタムアロケーター使えないよな?
- 846 名前:デフォルトの名無しさん [2018/06/06(水) 20:32:29.81 ID:sZLPzbQ0.net]
- >>826
O(1)で10個挿入したら、O(1)*10なんだから、結局O(N)じゃないの?
- 847 名前:デフォルトの名無しさん [2018/06/06(水) 20:34:19.38 ID:sZLPzbQ0.net]
- もしかして、std::unique_ptrを突っ込むのがすでに間違いで、std::anyを使えってことなんだろうか。
- 848 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 21:03:14.93 ID:9YbuVUhL.net]
- >>827
std::forward_listとそのイテレータだけでFIFOのQueueを実装できたりするよ イテレータを介したinsert_after()になるから要素を入れるコストはイテレータのコピー分、std::queueよりも高くなると思うけど std::queueはstd::dequeかstd::listを利用するから、std::forward_listで実装した方がメモリ使用量は少ない 単方向リストを使用して独自実装した方が低コストに抑えられると思うけどね まあ、再利用も良し悪しって事だね
- 849 名前:デフォルトの名無しさん mailto:sage [2018/06/06(水) 21:09:23.87 ID:9YbuVUhL.net]
- >>830
ごめん書き方が悪かった、1つの要素の挿入にO(1)って意味ね Linked Listは、挿入場所への移動にO(n)かかり、挿入にO(1)かかるから 最後の要素を指し示すイテレータを保持してたらpush_back()みたいなことも出来るよって話ね
- 850 名前:デフォルトの名無しさん mailto:sage [2018/06/09(土) 00:34:24.48 ID:l0w/1aK3.net]
- std::array の empty()メソッドって意味があるのか?と最近思ったので質問させてください
arrayは通常 array<int, 固定値>のように宣言してから使うと思うのですが、 empty()メソッドの戻り値は <int, 0> 以外は全てfalseでした。 つまり通常<int,(0より大きい整数)>で宣言して使う場合empty()はfalseしか返ってこない 気がするのですが、このメソッドは意味があるのでしょうか?
- 851 名前:デフォルトの名無しさん mailto:sage [2018/06/09(土) 05:56:11.66 ID:nuHHgQUg.net]
- >>834
テンプレートを使って異なる種類のコンテナに共通に使える処理を書くときに、他のコンテナ達と共通の関数を備えていると都合がいいからかなと思う。
- 852 名前:デフォルトの名無しさん mailto:sage [2018/06/09(土) 12:31:35.52 ID:pc7gEgF8.net]
- >>834
そのメンバの存在意味の有無に関わらず、コンテナ要件の1つだからね 他のオブジェクト指向言語でのインターフェイスや抽象クラスを用意していないだけで コンテナとして共通の要件(インターフェイス)が設けられている 例えば、size()、empty()、begin()、end()など 本来、動的なポリモーフィズムをするためにインターフェイスや抽象クラスを設けるけど vtableは高コストだから、ゼロオーバーヘッドの原則に則り使用していないのよ まあ、コンテナ自体STLの1つだからオブジェクト指向的な機能は意識していなかったと思うけどね 余談だが、聞いた所によるとテンプレートって最初マクロで実現しようとしてたらしいね
- 853 名前:はちみつ餃子 mailto:sage [2018/06/09(土) 12:50:19.63 ID:EdmRUNh7.net]
- 具体的にコンテナに求められる要求はここでまとめられているので参考になれば。
ja.cppreference.com/w/cpp/concept/Container クラスに求める要求を表現するための機能「コンセプト」は C++ の悲願としてずっと前から温められているのだけれど、 なかなか仕様に入らずに先送りされてるという状況。
- 854 名前:デフォルトの名無しさん mailto:sage [2018/06/11(月) 16:42:05.03 ID:SE5SjeC/.net]
- ファイルから読み込んだバイト列の先頭部分を参照して、
それがJPEGファイルなのか、PNGファイルなのか、などを判定したいのですが、 どの程度の判定をすればよいものなのでしょうか。 例えばJPEGファイルなら、先頭3バイトを{0xFF, 0xD8, 0xFF}とmemcmp()で十分なのでしょうか。
- 855 名前:デフォルトの名無しさん mailto:sage [2018/06/11(月) 16:50:15.52 ID:9mmiVsnm.net]
- 十分かどうかは時と場合による
- 856 名前:放置された蟻人間 mailto:sage [2018/06/11(月) 16:51:12.74 ID:7op9QnGW.net]
- 画像ファイルには、過去にいくつか脆弱性が確認されている。使用において、脆弱性の存在が致命的ならば、きちんとチェックすべきだし、
処理スピードを優先するなら、memcmpで十分。
- 857 名前:デフォルトの名無しさん mailto:sage [2018/06/11(月) 17:03:57.96 ID:SE5SjeC/.net]
- すいません、十分というのは、ファイルの破損や脆弱性関連は置いておいて、
他の形式の正常なファイルも拾ってしまわないかということです。 JPEGの場合、先頭の3バイトを判定すれば、他の正常なファイルが引っかかることはないのでしょうか。
- 858 名前:デフォルトの名無しさん mailto:sage [2018/06/11(月) 17:06:17.81 ID:3AghcpDH.net]
- 中身見ないなら、拡張子でもできそうだが
- 859 名前:デフォルトの名無しさん mailto:sage [2018/06/11(月) 17:12:32.50 ID:oqoWhxjw.net]
- 3バイトをランダムなデータと比較する場合、1/16777216の確率で誤認する
ファイルを最後までパースして、JPEGデータとして読み込めるかどうかチェックするのが確実だが
- 860 名前:はちみつ餃子 mailto:sage [2018/06/11(月) 17:40:03.88 ID:CXPnR3I1.net]
- >>841
POSIX には file コマンドがあってファイルの種類を判定できるけど、その実装はヒューリスティックだよ。 参考になるとは思うから読んでみるのもいいんじゃない? ライセンス的に OK ならそのまま流用してもいいかも。 どの程度の精度で判定すべきかは状況によるので総合的に考えてとしか言えない。 例えば、 jpg ではないファイルが多数ある中から jpg を探すというような状況だったら、 先頭をちょっとだけ読んで jpg っぽかったら全部を読んで詳細に判定するというのでもいい。 ほとんどが jpg なのだったら、いちいち詳細に判定するのは速度的に遅くなるけど、それが許容できるのか、 許容できないのであればどの程度まで緩い判定にしていいのか、バランスの問題。
- 861 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 12:54:07.45 ID:xDeIiE2o.net]
- なぜ多数から探すかどうかで判定方法が変わるのか
- 862 名前:はちみつ餃子 mailto:sage [2018/06/12(火) 13:09:55.18 ID:U9ShKAeR.net]
- >>845
速度とかとのバランスだって書いてあるつもりだけど、わかり難かった?
- 863 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 13:15:57.78 ID:BvPEMwcC.net]
- 明らかに一致しない時は瞬時に判断出来る
ヘッダですぐにわかるので jpgではあるんだけど 非対応フォーマットとか一部化けてて表示出来ないとか そういう判断が難しい
- 864 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 13:34:24.68 ID:BvPEMwcC.net]
- はちみつはJPGを扱ったことが無いってのがよく分かる
- 865 名前:はちみつ餃子 mailto:sage [2018/06/12(火) 14:45:14.29 ID:U9ShKAeR.net]
- >>847
えっ? だからまずは先頭をちょっとだけ読んでみる (この判定だと false positive はあっても false negative はない) という話なんだけど。
- 866 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 16:23:32.57 ID:LTqXdgcV.net]
- 元の >>838 の質問に戻れば「どんなファイル群を扱うのかによる」としか
言いようがないんじゃないか? 極端な話、行儀の良いファイルだけなら拡張子で判定しても大丈夫。 (拡張子が間違ってるけど)一般的なファイルばかりなら先頭の何バイトかで判定。 悪意を持って偽装ヘッダや追加情報エリアまで利用してる可能性を気にすれば JPEGの規格に準拠してるファイルでさえ危険、というレベルまであるかも。
- 867 名前:はちみつ餃子 mailto:sage [2018/06/12(火) 16:44:07.95 ID:U9ShKAeR.net]
- ある程度は信じて割り切るしかしょうがない。
- 868 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 17:43:08.97 ID:RH6dhGDk.net]
- JFIF以下のJPEG出す機材って監視カメラ以外見たことないなぁ
実運用上はJFIFとEXIF以外は対象外でも良いのかも
- 869 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 17:56:59.93 .net]
- ポインタでないなら、継承した関数を呼び出すときに、仮想テーブル参照による動的オーバーヘッドはないのですよね?
- 870 名前:はちみつ餃子 mailto:sage [2018/06/12(火) 18:20:08.25 ID:U9ShKAeR.net]
- >>853
Yes それが仮想関数であろうとも、 オブジェクトへのアクセスがポインタ経由でないならば どの関数を呼び出すのかコンパイル時に確定可能なので、 仮想関数テーブルにアクセスする必要はない。 (はずだと思うが言語仕様での保証はないだろうし、 実態がどうなってるか確かめたことはないんで、 誰かやってみてくれんかな。)
- 871 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 18:35:01.32 ID:Q/HiJGFf.net]
- >>849
ファイル判別の一般論じゃなくてjpgの判別ですよ jpgの判別方法を語ればいいんです 文字コードと違ってあやしいとかはなくて APPnの中数バイト見れば簡単にわかるんですよ 文字でJFIFとかExifとか書いてあるわけなんで 偽装が無いならこれで十分 あとは 対応フォーマットであるのか 正しいフォーマットであるのか 実際にデコード出来るのかどうか などを判別する必要があるかどうかでその先が決まる
- 872 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 18:43:20.13 ID:RH6dhGDk.net]
- >>855
baka?
- 873 名前:デフォルトの名無しさん mailto:sage [2018/06/12(火) 18:57:45.80 .net]
- >>854
ありがとうございます
- 874 名前:はちみつ餃子 mailto:sage [2018/06/12(火) 20:19:36.50 ID:U9ShKAeR.net]
- >>855
何言ってんの? その偽装があるかもしれん (ということも想定に入れるかどうは場合による) という話なんだけど。
- 875 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 00:32:03.88 ID:21BMiWPP.net]
- >>841を読んでの発言?
日本語が読めないの?
- 876 名前:はちみつ餃子 mailto:sage [2018/06/13(水) 01:55:04.01 ID:3eXA0K0W.net]
- >>859
なるほど、偽装に騙されるのは脆弱性の内 (で、それはないという前提が提示された) という解釈? 判定を誤りうる (データを作れる) のとセキュリティ的な欠陥をなんとなく区別してたけど、 質問者の感じからすると、確かに偽装で騙されるのは脆弱性の内かな。
- 877 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 01:56:34.26 ID:l7UBIPff.net]
- >>855
JPEGの規格書を読んだ事が無いだろう
- 878 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 07:50:57.05 ID:vaxyQxvX.net]
- 昔ゲーム機のハックで偽装した画像ファイルを読み込ませるってのがあったような気がする。
- 879 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 08:14:06.81 ID:7lldK1Da.net]
- >>838 >>841 を合わせた質問の意図からすると、
JPEG以外で先頭3byteが {0xFF, 0xD8, 0xFF} のファイル形式が存在するか、 普通に出回ってるか? という問題じゃないのかな。
- 880 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 09:42:34.58 ID:V88S+L9t.net]
- ゲロトラップとして普通に出回ってないかね?
- 881 名前:デフォルトの名無しさん [2018/06/13(水) 09:46:09.42 ID:Lf/dU7gs.net]
- テンポラリオブジェクトについて質問です。
ロベールの本ですが、 「 Hoge Two() { Hoge n(2); return n; } int main() { Hoge hoge(1); hoge = Two(); とした場合、基本的には n のコピーがいったん作られて、それが hoge に 代入される形になります。このコピーこそが、テンポラリオブジェクトになる わけです。 」 と書かれていますが、なぜわざわざ n のコピーを作るのでしょうか? n は Two() 関数を抜けたら消えてしまいますが、これを消さずに、 返した方が効率的な気がします。
- 882 名前:デフォルトの名無しさん [2018/06/13(水) 10:17:19.41 ID:Lf/dU7gs.net]
- ・テンポラリオブジェクト = n のコピー
・代入により、 hoge に テンポラリオブジェクトがコピーされる。 これはなんか非常に無駄なことをやっているように思ってしまいます。 hoge に 捨てずにとっておいた n を参照させれば十分のように思います。
- 883 名前:838 mailto:sage [2018/06/13(水) 10:17:36.81 ID:818/kKId.net]
- みなさんありがとうございます。
話が難しい方向に進んでしまってすいません。 勉強させていただきます。 元々の疑問は>>863の言われるとおりで、 他の形式の画像をJPEGだと誤判定してしまわないか、 さらに言うと、先頭が{0xFF, 0xD8, 0xFF}以外のJPEGファイルも存在していて、 JPEGファイルを見逃してしまうことがあるのか、ということでした。
- 884 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 14:58:14.75 ID:54SDWBzN.net]
- >>865-866
そういう時こそ右辺値参照ですよ hoge = std::move(Two()); でもこんな事をしなくても大抵戻り値最適化(RVOやNRVO)でコピーコンストラクタは呼び出されない 明示的にムーブコンストラクタを無効にするとコンパイルエラーが発生するはず Hoge(Hoge&&) = delete;
- 885 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 14:59:33.86 ID:54SDWBzN.net]
- そしてこの場合代入演算子をオーバーロードしてやるとそちらが使われる
Hoge& operator=(const Hoge& hoge) { std::cout << "assign operator called." << std::endl; return *this; }
- 886 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 20:08:20.11 ID:VLQaO2hj.net]
- (最適化をおいとくと)値渡し/値返しってそういうもんじゃん
Two()内の変数nは自動変数だからスタックに作られる とっとけないじゃん
- 887 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 21:00:21.79 ID:qH/FTczC.net]
- まあ2回コピーされるのを1回に抑えるための最適化でしょう
- 888 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 21:08:53.19 ID:buJbRccy.net]
- 確実なのは戻り値じゃなくて参照、もしくはポインタにすること
- 889 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 21:40:28.10 ID:GheUJm4W.net]
- >>872
それヤバくね?関数を抜けた途端消える存在を参照するとか
- 890 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 22:09:20.49 ID:1EWuco5t.net]
- 呼び出し元から参照を渡してそこに返してもらえってことじゃなくて?
- 891 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 22:13:11.63 ID:21BMiWPP.net]
- もちろんそう
昔ながらの方法
- 892 名前:デフォルトの名無しさん mailto:sage [2018/06/13(水) 23:23:40.79 ID:MDGDBDRC.net]
- -Wreturn-local-addr みたいなwarningじゃなくて規格でエラーにすれば873みたいな勘違いは無くなるのにな
|

|