C言語相談室(上級者専用)

■ このスレッドは過去ログ倉庫に格納されています
2018/03/02(金) 22:48:03.65ID:2Cs+DkMh0
C言語の話題のみ取り扱います。C++の話題はC++スレへ。
上級者専用です。10,000行程度のソースを扱えない人は以下スレへ。

C言語なら俺に聞け
https://mevius.5ch.net/test/read.cgi/tech/1519046038/

適宜以下を使用してください。
https://paiza.io/
https://ideone.com/
http://codepad.org/

C11
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf

C99
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
http://kikakurui.com/x3/X3010-2003-01.html

C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/

JPCERT C コーディングスタンダード
https://www.jpcert.or.jp/sc-rules/

次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured
2018/05/12(土) 15:19:25.30ID:V7PQOWmO0
>>44
その言い方、Rustを結構使っているように見えますが、違いますか?
Cが「ミニマルだ」ということには——少なくともISO C99規格を見るに——あまり賛同できないんですが、
それはまぁ、置いておいて、私がRustを触った限り、あれはC++の代替に見えます。
C++が現在も(規格を拡張する方向に)積極的に開発されているのは分かっていますし、
「だからRustが取って代わる必要はないのだ」という理論的帰結も理解できますが、
ポインタの安全性ややはり名前空間の宣言あたりを見ると(あくまで触りですが)どうしてもC++の文法を彷彿とさせるの
構造が多いように思いますね。
2018/05/12(土) 15:20:29.04ID:V7PQOWmO0
あ、すいません。一行目で使ったことがないと断られていました。
いや、なぜ確認しなかったんだろう、失礼しました。
2018/05/18(金) 23:11:30.66ID:qSToTkUZ0
>>45
> あれはC++の代替に見えます。
それは正しい。
というか、「後継」と「代替」はこの場合明確に区別して使われるべきだ。

・「○○の後継」---○○言語を発展させたもの。
 上位互換であり、○○言語と共に使うことを考慮されている。
・「○○の代替」---○○言語の代わりに使うもの。
 基本的に○○言語と一緒に使うことはない。排他的使用となる。

Rustの謳い文句は、「効率的なCバインディング」であって、
「効率的な『C++』バインディング」ではないんだよ。
CのDLLは当然呼べるが、C++のDLLを呼べるように出来ているか?
C++の「後継」と言うのなら、基本的にはC++の資産を全活用できる方向になってないといけない。
ただしそもそもC++は「後継」用のAPIを整備して無いと思うんだが。

C++の例外「実装」についてググッても、まともな文献が出てこないだろ。
おそらくあれは「実装」まで言及した仕様ではなく、「言語としての動作規定」しかされてないんだ。
(元々C++はそういうノリだし)
だからtry-catchを含んだ関数をDLL化できて他言語から呼べるかはかなり疑問だ。
勿論、昔からの課題だから今は解決されているかもしれんが。
> Throwing C++ exceptions across DLL boundaries is only possible when all modules use the same C++ runtime,
> in which case they share a heap as well. But this can be a maintenance burden,
> especially when libraries from multiple vendors are involved, so it is discouraged.
> https://stackoverflow.com/questions/5107948/throwing-c-exceptions-across-dll-boundaries

だからCのDLLは他言語(Rust/Ruby/C++/C#)等から直接呼べるが、
C++のDLLを呼べます、と謳っている奴はいないだろ。
この点において、C++は後継言語の存在を許していない。

だからRustはCの「後継」であり、C++の「代替」というのが妥当な見方なんだよ。
実際、RustがあればC++を使う意味がないだろ。
2018/05/18(金) 23:12:06.97ID:qSToTkUZ0
Cは大規模コードに対するサポートが全くない。
とはいえ、「やれば出来るだろ by Linus」なのは事実だが、実際それでは辛いわけで、
コンパイラに任せられるところは任すという方向で上手く手抜きできるように進化させたのがC++だ。
Rustも同じ方向なのだから同様の物になるのは当たり前。
当然、どちらかを使用すれば事足り、RustとC++は排他関係になる。
つまり、RustはCの「後継」であり、C++の「代替」だ。おそらくここまでは大体の人が納得するはず。

問題はCの「代替」にもなり得るか?という点であり、だからそこが議論されているわけだ。
今現在もCを使うメリットは速度面しかない。したがって速度面のデメリットがなければ良く、
「ゼロコスト抽象化」等、速さにこだわっているのはそこなんだよ。

ただ俺個人としては、全体を一つの言語で書く必要なんて全くなくて、
NumPyのアプローチ、つまりどうでもいいところ(9割以上)はスクリプト言語で書き、
必要なところだけCのDLLを呼ぶ、というのが正しい気がするが。C#もこの方向だね。
この場合、リソース管理をGC言語側に任せられ、
また個別関数単位での切り出しになり、
DLL内関数はお互い独立(非依存)で行っても1,000行とかでしかなく、
Cでも全く問題にならないんだよ。
だからRustも微妙に中途半端な方向だとは思うが、
もし仮にCを代替できるのなら、それは素晴らしいと思うよ。
49デフォルトの名無しさん (ワッチョイ 89fa-9WOx)
垢版 |
2018/05/23(水) 19:34:50.63ID:Au5e7VGg0
僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』

8UTJJ
2018/05/24(木) 16:09:00.92ID:6FiN0bsr0
114.149.223.252
2018/07/02(月) 19:57:22.74ID:tgZxuU9E0
RustはCの「後継」であり、C++の「代替」
これでRust周りの(宗教戦争じみた)論争の理由が理解できた。
52デフォルトの名無しさん (ワッチョイ 45fa-2e90)
垢版 |
2018/07/04(水) 22:51:20.65ID:gFgZc5FG0
NTB
2018/07/09(月) 23:31:02.20ID:bV3eVpry0
NTR
2018/07/26(木) 02:18:42.03ID:BvZq73xc0
ポインタってさ、「指示子」と和訳したら分かりやすいと思うんだが
そうしなかった理由ってなんだろ

それとも俺の感性がおかしいだけか
2018/07/26(木) 02:38:35.19ID:rK3i9Ft7a
昔、筧先生ってひとがいて…
2018/07/27(金) 01:03:48.10ID:GvW3yrkV0
>>55
kwsk
57デフォルトの名無しさん (ワッチョイ 6f9f-53i4)
垢版 |
2018/07/27(金) 03:35:26.85ID:O4NPrPXG0
ちょっと10回言ってみ

言い辛いよな
2018/07/27(金) 17:21:35.88ID:GvW3yrkV0
え? なに? もしかして昔なにか荒れる原因になった ANDOR 問題のある人が使ってた用語なのか。
若いもんで知らなかったわ すいません。
2018/07/28(土) 09:57:54.67ID:VMG9DnUG0
「指示子のgcc拡張」みたいな早口言葉モドキができて面白いかも。
60デフォルトの名無しさん (アウアウエー Saaa-2QVD)
垢版 |
2018/07/28(土) 13:58:33.27ID:39ICzHjEa
指示子の指示子
指示子の配列
配列の指示子
配列の指示子の指示子
指示子の配列の指示子
ダブル指示子
配列の指示子の配列 👀
Rock54: Caution(BBR-MD5:1341adc37120578f18dba9451e6c8c3b)
2018/07/28(土) 15:05:25.84ID:BHZfW2WL0
>>60
なんかおこられてやんの
62デフォルトの名無しさん (アウアウエー Saaa-2QVD)
垢版 |
2018/07/28(土) 15:08:57.51ID:39ICzHjEa
こんなので目玉付くんだなω
2018/08/05(日) 00:49:09.36ID:fZk3Cg460
C99(ISO/IEC 9899:1999)で,main()関数の型がintな理由ってどこかに書いてあるっけ。
今ふと,リターンコードって0から255の整数なんだから
uint8_t main(...
としても問題ないよなと思ってさ。
2018/08/05(日) 00:50:03.59ID:fZk3Cg460
すまん。途中で送信してしまった。
そうするとコンパイラにmain()の型はintだと怒られた。
2018/08/05(日) 01:34:55.28ID:/g7t90jda
型がintというのは決まってる。
実際の範囲は実装依存。windowsだと違ってなかったか?
66デフォルトの名無しさん (ワッチョイ a39f-Xflc)
垢版 |
2018/08/05(日) 07:12:37.38ID:cdvogGHQ0
main()が戻す値は呼び出す側の問題だとは思うが、その部分(crt0とか)は普通はC言語に合わせてintを
返してくると想定して作られていると思う。しかしその部分まで自作するというのであればなんでもアリではある。
https://en.wikipedia.org/wiki/Crt0
2018/08/05(日) 08:37:27.73ID:5+7WSxVZ0
シェルが受け入れるコマンドの終了ステータスの値が0-255の範囲、
てのはUNIX系もDOS系も(珍しく)一致してるのね。
unsigned char の外に出ないことは間違いないわね。

ANSI以前の古いCでの「宣言なしに使われた外部関数はintの値を返す」
という仕様が、規格化したときに互換性の問題を生まないように
main()の返り値はintと決めたんじゃないかしら。
2018/08/05(日) 12:29:08.02ID:fZk3Cg460
なるほど。まあ過去互換性は重要だしね。
ただ,CはPOSIXというOSの標準規格を定めてる団体が関与して設計されてるから「リターンコードは0--255。よってmain関数の型はuint8_t」と割り切ってくれてもいいのになぁ。
とか勝手に思ったりしてる。
2018/08/05(日) 13:13:57.79ID:/g7t90jda
まあintが妥当だろう。
しかし、_exit()に渡すのがintでwait()した時も一応exit statusはintだよな。
どこで上位ビット欠落させてんだ?
70デフォルトの名無しさん (ワッチョイ a39f-Xflc)
垢版 |
2018/08/05(日) 18:30:06.69ID:cdvogGHQ0
>>69
OSの中だ。_exit() はシステムコールだし。
まあでも UNIX 系 OS じゃないならこれは違っているかも知れない。
2018/08/06(月) 01:15:24.28ID:/d0+B2Ty0
ちょっとCの範疇を越えた話になるけど
リターンコードが0--255ってどういう段階で決定されたんだろう。
DOSとUnixが同じ範囲のリターンコードを持ってるって、偶然とは考えがたいんだけども
2018/08/06(月) 02:07:20.39ID:xc/1a6k50
unix等の先行者を参考にDOSを作ったんだから
2018/08/06(月) 07:45:24.26ID:1aQ1rnwf0
DOSの終了ステータスはUNIXの仕様をそのまま使用だと思う。

UNIXの方は、子プロセスを作って別の仕事をさせるって定型処理で、
「親プロセスで子プロセスの終了を待つ」ためのwait()系の関数が、
・子プロセスが正常終了した場合は子プロセスの終了ステータス
・子プロセスが割込みで中断された場合は割込みの種類
という2つの情報を1個の返り値で戻すことと関係あるのじゃないかな。

1個の整数値を上位と下位のビット群に分けて別の情報として使うために
それぞれの情報量を1バイトずつに制限した、と。
2018/08/06(月) 08:23:05.65ID:jTWGCXc00
UNIX板のおじさんに聞いてみたら
2018/08/26(日) 08:24:46.45ID:dLFVucRz0
auto変数で char配列を可変長で動的に確保する方法は無いかな。
アセンブラレベルならスタックポインタを操作すれば可能だと思うが。
文字列処理の内部バッファとして入力に合わせたサイズを確保したいんだが、とりあえず今は固定長バッファとそれを超える場合は malloc でやってる。
2018/08/26(日) 09:09:31.40ID:Vxoswi+gd
alloca
2018/08/26(日) 09:18:39.26ID:O9adGcKd0
>>75
gcc使うなりalloc()使うなりすればいい
とりあえず
vla c言語
で、ぐぐれ
2018/08/26(日) 09:29:28.31ID:ik1BtrwR0
>>75
alloca
標準ではないけどほぼ標準扱い。(殆どの環境で使える)
ただし realloca は無いので注意。
2018/08/26(日) 09:31:08.30ID:dLFVucRz0
>>76-77
ありがとう、まさにぴったり。
言語レベルでの可変長配列は C11 から(オプションだけど)入ってるんだね。
90年代からメンテされてるコードだからそっちは使えなそうだけど、alloca を検討してみる。
2018/08/26(日) 10:56:05.32ID:O9adGcKd0
>>79
環境わからんからなんとも言えんが組込みとかWindowsとか意外にスタックサイズがしょぼい環境あるから気を付けてね
2018/08/26(日) 11:49:56.37ID:hQMrm9ZNa
いやいや、C99からだよ。C11でオプションになった。答える方はそのくらい知っとけよ。
まあ入力が小さいのが予め分かってないと使いにくい機能だよ。
2018/08/26(日) 13:04:10.92ID:HHP/3bjy0
>>75
その入力というのがファイルからの1行入力みたいなものならば getline() 使ってしまえば
自分で考える必要がなくて楽だ。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/getline.3.html
2018/08/26(日) 15:51:52.71ID:0Dyu3Dip0
発端の >>75 の意図次第だが、free()しなくても安全に蒸発して欲しいとか、
ヒープの確保と解放の処理時間を嫌っての話ならgetline()はちょいと違うね。
文字数の予測が難しい入力を扱うにはとても便利なんだけど。

それにしても「上級者専用」って看板が架かってることを意識すると
このスレッドは書き込みにくいな。気後れしちゃう。
84デフォルトの名無しさん (ワッチョイ ed68-DNis)
垢版 |
2018/08/26(日) 16:14:52.46ID:tQPCeAJ90
alloca
2018/08/26(日) 16:21:37.62ID:hQMrm9ZNa
動的確保が無難なんだよね。最後にfreeすればいいだけだし。
最近まで知らなかったんだけどscanfで%msで動的確保してくれるの便利だな。scanf自体はなかなか難しくて使いづらいが…
2018/08/26(日) 17:31:54.88ID:dLFVucRz0
>>81
あ、C99で入ったのをC11でオプショナルに格下げ(?)されたってことか。
処理系によっては厳しい実装なのかな。

やりたいことってのは文字列のエスケープを含んだ組み立てなんだけど、使用するエスケープ関数がありものでその仕様は入力文字列長に対して2倍以上の出力バッファを与えないといけないことになってる(出力サイズを指定して打ち切らせることができない)。
実際に2倍に膨らむことは稀だし、エスケープするのも文字列中の一部なので、自分の処理で最終的に出す出力結果は論理最大よりかなり小さくなる(自分の処理は指定された出力長で打ち切る)。
まず来ることが無い事態のために論理最大の配列を取っておくのもどうかと思い、いい方法があるかここで相談させてもらった。
しかし想定外のことが起きちゃった時にどうなるべきかを考えてどうするかを決めるから、もしかしたら動的配列の意義が無くなって別の方法にするかもしれない。
この処理自体は高頻度で呼ばれるから、高速で省メモリそして内部的な都合での打ち切りは極力避けた作りにしたいって感じ。

いろいろコメントありがとう
87デフォルトの名無しさん (ワッチョイ ed68-DNis)
垢版 |
2018/08/26(日) 17:43:02.62ID:tQPCeAJ90
あらかじめプールしておいて使いまわす
足りない時だけ臨時で増やす
2018/08/26(日) 18:09:50.26ID:Vxoswi+gd
ReactOSというOSでフォントエンジンの改良を行っているが、
Google Chromeというブラウザでおかしくなる。
何故かEIPレジスタがゼロになって、初回例外が発生する。KDBという付属のデバッガでトレースしたが、
どこの関数で例外が発生しているかわからない。
たすけて。。。
2018/08/26(日) 18:15:57.28ID:Vxoswi+gd
これがイシュー。
https://jira.reactos.org/browse/CORE-14926

これが問題のコミット。
https://github.com/reactos/reactos/commit/35f62fc5ba0b69e7335ff41400cb3b45660f4557
2018/08/26(日) 18:22:22.54ID:Vxoswi+gd
晒しあげ
2018/08/26(日) 18:39:01.79ID:Vxoswi+gd
スタック破壊の可能性か。。。
2018/08/26(日) 19:04:13.59ID:ik1BtrwR0
>>85
> 動的確保が無難なんだよね。最後にfreeすればいいだけだし。
結局の所、結論としてはそうだね。

>>86
多分素直にmallocする関数をラップして使う方がいい。

仕様の動向自体は知らんが、
> 処理系によっては厳しい実装なのかな。
技術的にはこれはない。alloca相当(ポインタ相当)にすればいいだけなので。
ただ、間接アクセスになるから速度は落ちるし、
mallocに対しての利点は『自分で』freeしなくて済むことくらいしかない。
(『自分で』ソースに書かなくてよくなるだけで、速度上のメリットはない。
reallocaが無い為、最初のバッファ(=サイズが不明)はヒープ上に動的確保するしかなく、
自分で書いてなくてもどこかでfreeされてるだけだから。なら最初からgetlineでもいいし)

ただ、そちらの実装は(おそらくバッファオーバラン対策で)一旦固定長バッファに取り込み、
その後alloca領域に対してのコピーか?
ならまあ一応freeしなくていい速度上のメリットは残るが、
一般的にはスタックサイズ管理のコストが増える方が問題とされ、その実装はないとも思うが。

結局、allocaもイマイチなんだよ。だから標準にもなりきれない。
2018/08/26(日) 19:12:21.53ID:ik1BtrwR0
>>83
>>1,13読んで以下にどうぞ。
C言語なら俺に聞け
https://mevius.5ch.net/test/read.cgi/tech/1534430162/

>>12
>>89
それがこのスレの正しい使い方かもしれんね。
ぱっと見て分かるものでもないけどさ。
2018/08/26(日) 19:20:25.22ID:uLlG7vHAa
allocaとか動的サイズ指定の配列はスタックだから基本的にはmallocするよりは速いよ。頑張っても同等。
繰り返して呼ぶなら差が出るかもね。
2018/08/26(日) 19:53:34.99ID:ik1BtrwR0
ああ、言い直しておくよ。
allocaとmallocなら、

確保:allocaの方が速い
使用:同速(ただし初回からキャッシュが当たる分allocaの方が速い)
解放:freeの必要が無い分、allocaの方が速い
 (ただし実装によっては上位でfreeしてるだけであり、同速)
管理:通常、ヒープサイズ>>>>>>スタックサイズの為、サイズ管理が必要

速度差が見えるような使い方が出来るのなら、ある意味大したもんだと思うよ。
2018/08/26(日) 20:17:14.11ID:iSNBdVUGa
スタックって確かスレッド毎に肥大化してくよね?
で、肥大化してもスレッドが停止するまで縮小しない

あってる?
2018/08/26(日) 20:19:54.25ID:r4V1HxTD0
関数から戻るとき(エピローグ)にスタックは縮小することがある。
2018/08/26(日) 20:26:06.20ID:Vxoswi+gd
実際のx86 CPUでスタックポインタを表しているのが、ESPレジスタの値。スタックサイズの増減はESPの書き換えに過ぎない。
2018/08/26(日) 20:30:48.56ID:dLFVucRz0
流れのついでに聞いてみたいけど、malloc はスレッドセーフでしょ。
てことは内部で排他をかけてると思うけど、となるとマルチスレッド下で malloc や free を多発させるとパフォーマンス的に良くなかったりしないかな。
言ってなくてごめんだけど、今回の処理はマルチスレッドで動くんだ。
なのでバッファはスタック上に取れると都合がいいという事情もあるし、特別な初期化手順や終了手順も用意したくないから事前に malloc して使い回すってのもやりづらい。

ちなみに動作環境は x86 linux だから、alloca は SP をズラすだけの非常に高速な実装になってるんじゃないかと想像してるから、関心は高い。
でも、最悪でもスタック上に収まるバッファという前提にするなら最初から論理最大サイズ固定のバッファで良くね?なんて話もあるから、実際にどうするかはこれから検討。
2018/08/26(日) 20:39:55.03ID:QMrmo6TZM
glibcのmallocならサブarenaから獲得してくるから性能問題にはならないらしい
101デフォルトの名無しさん (ファミワイ FF49-DNis)
垢版 |
2018/08/26(日) 21:03:16.49ID:KvfxyzVvF
そうだよ
条件後出しω
2018/08/26(日) 21:06:39.43ID:ik1BtrwR0
>>99
サイズの問題がないのならallocaを使うことに問題はない。
mallocより遅くなる理由もないので。

ただ、普通に組めば分かるが、
> malloc や free を多発させる
ってのがあり得ない。
仮にこれがallocaで有効に代用出来るとするなら、再帰下降パーサ等、「再帰」が必要になるが、
再帰下降パーサの場合はインミュータブルでよく、元の文書をオフセット付きで参考して終わりだ。
再びallocaすることはない。
同様に、ループでパースするのなら、ループの外でmallocして十分な領域を確保し、
そこに上書きで使うことになる。だからmalloc/freeは1回ずつで済む。

もう一度言うが、allocaはスタックだから、「再帰」しないと領域を追加出来ない。
この使い方は普通無いし、君もやって無いと思うよ。
でも、普通のmallocを全部allocaで代用しても、サイズ以外の問題は無いから、可能ならそれでもいい。
2018/08/26(日) 21:08:26.06ID:ik1BtrwR0
> alloca は SP をズラすだけの非常に高速な実装になってるんじゃないかと想像してるから
これはその通り。

> 最初から論理最大サイズ固定のバッファで良くね?
これもその通り。上記ループなら普通これで行く。
それがスタック上で問題になるサイズならmalloc/freeが1回ずつ必要になる。
だから君の今の実装>>75もさほど悪いわけでもない。

今風の「実装を外に漏らさない」方針なら子関数でmalloc/freeやallocaすることになる。
おそらくそれで考えているのだと思うが、元々のCの思想はそれとは違い、

char* buff = (char*)malloc( ... ); // または char buff[2048]; 等
while (....) {
parse_func(buff, .... );
}
free(buff);

として外側で確保し、それをparse_funcに渡す。
これにより、変数の寿命とスタックの動作を一致させ、freeし忘れもなくなる。
この方法だと、allocaで毎回「SP をズラすだけ」すらする必要なく、parse_func内は最速になる。
(allocaを毎回繰り返すよりも速い)
2018/08/26(日) 21:12:44.54ID:uLlG7vHAa
あくまで処理系依存の話として…
マルチスレッド固有の問題はほぼない気がしますね。malloc/freeは単に別の領域確保していくだけだしスタックの場合はスレッド生成時に確保すると。
で、まあmallocの実装はそこまで悪くないと思うけどスタックが速いし、さらに静的領域の方がちょっと命令数は少なくなるでしょう。
2018/08/26(日) 21:36:27.43ID:dLFVucRz0
>>102-103
いろいろありがとう。材料は揃ってると思うので、最終的にどうするかはこれから決めるよ。

>>104
malloc は内部的にはヒープから領域を切り出してくるわけで、切り出したチャンクは恐らくリンクかなにかで管理してるはずでしょ。
これはプロセス単位で一式だから、マルチスレッドでよってたかってこの構造を更新するには排他は欠かせないと思うんだがどうなんだろ?
切り出されたメモリがマルチスレッド下でどうかという話ではなく。
>>100 の内容はちょっと分からないから調べてくるが、結局は誰かが排他してるんじゃないのかな。
2018/08/26(日) 21:52:41.59ID:QMrmo6TZM
>>96
実行環境依存だが、win/linuxならその認識で良い
allocaは便利だがスタックの肥大化を加速させるので
環境によっては注意が必要

>>105
興味があれば
https://youtu.be/0-vWT-t0UHg
2018/08/26(日) 22:03:50.42ID:r4V1HxTD0
>>97-98 間違いです。すみません。
2018/08/26(日) 22:07:11.30ID:ik1BtrwR0
>>105
以下読め。マルチスレッドに関する疑問点については全部書いてあるから。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/malloc.3.html
2018/08/26(日) 22:08:38.19ID:uLlG7vHAa
>>105
ナイーブなmallocの実装はそうです。中央集権的。同時に動くのは1個だけ。でもクリティカルセクションはそんなに広くないかも?
まあ実装はいろいろあります。
2018/08/26(日) 23:49:28.30ID:dLFVucRz0
>>106
すげーおもしろかった!
マルチスレッドでどうやってるかについても分かったよ。
過渡期の性能を犠牲にして使っていくうちにいい状態に収束するようにしてるのね。
しかし malloc のコードが 5000行てw
ただ、mmap すればメモリ管理のコストが小さい的な言いぶりはどうかなって気はするな、動画の中でもツッコミ入ってるっぽいけど。
結局カーネルだって何らかの形でアドレス空間の空きを検索するし、アドレス空間を割り当てる処理にしても排他はかけてるはずだから、それなりのコストはかかるし競合の問題もあるよね(ユーザーがやる処理よりも高効率だろうと思うけど)。

>>105
malloc の話を持ち出したのは、排他とかで結構遅いんじゃね?ってのが出発点なので、
排他はしてるって言うし mmap だからという説明じゃ解決って話でもないかなって感じ。

>>109
>>75 の頃の時点では K&R アロケータ程度の認識だったからマルチスレッド下ですげー遅そうな印象だったけど、さすがによく考えられているということは分かったよ。


ちなみにこれも読み始めてた。
https://www.valinux.co.jp/technologylibrary/document/linux/malloc0001/
>>106 の動画を見てだいぶ見通しがよくなった。
2018/08/27(月) 00:24:32.33ID:+HD/yYG+0
>>63
5.1.2.2.1
2018/08/27(月) 04:36:47.89ID:y2YT/eYl0
>>111
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf#page=24
ここか
2018/08/28(火) 10:01:58.54ID:AJzSIbICa
>>106
サンクス
2018/09/01(土) 15:23:05.79ID:Z9gelboG0
POSIX準拠を念頭にC言語を書かれている方に訊きたいのですが、機能検査マクロって実際どのように使われていますか
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600
↑僕はこのくらいであればシステム互換性は担保されると思ってるんだけど
未だにPOSIX 1998にしか対応してないOSやコンパイラとかあるんですかね。
少なくとも_XOPEN_SOURCEが600以上じゃないと<math.h>においてM_PI定数が扱えないので
数式処理のプログラムをよく書く身としてはちょっと困るんですけども……。
2018/09/01(土) 15:25:50.73ID:AtDk99X7d
>>89
解決。ヌル文字忘れ。
2018/09/01(土) 16:42:41.27ID:PErE712pa
好きな人が古い環境を使っているという事情でもなければ、単に無視すれば良いのでは
2018/09/01(土) 16:56:39.73ID:AtDk99X7d
>>114
CMakeで環境を判定して、マクロを定義するのが王道だと思う。
2018/09/01(土) 18:20:25.47ID:vZp6TokWM
#ifdefでM_PIがないときだけ自分で定義するのが手っ取り早いと思うけど。
2018/09/01(土) 18:57:55.32ID:uNlfHVUP0
>>115
乙。てかreactOSって使い物になるのか?
無理してWindows使うよりは、素直にLinuxに逃げるのが順当だと思うが。
2018/09/04(火) 02:12:16.08ID:I66W1B5fd
>>119
使い物にするのが、依頼人の要望だから、私はそれを、果たすのみ。。。
2018/09/24(月) 03:37:05.87ID:1deJaFMg0
上級者ではないんだけど 経験豊富な人に訊きたいのでここに書きます
https://git.musl-libc.org/cgit/musl/tree/include/stdlib.h
↑ここなどを見るとEXIT_SUCCESSは0で固定されています(OSによる場合分けがない)。
ということは少なくもMusl LibCプロジェクトは正常返り値を0と決めてかかっているということでしょう。

WindowsやUnix系のOSでは正常返り値は0ですが、ほかの値は絶対に考えなくていいのでしょうか
みなさんはいままで正常返り値が0でない処理系(というかOS)を見たことなどありますか。
2018/09/24(月) 04:02:22.36ID:bIT2p0fxa
0が成功を示すと規格で決まっております。
2018/09/24(月) 12:40:59.88ID:indqm+5q0
>>121
もしプロセス終了コードの具体的な数値(数値かどうか)が異なるシステムがあるなら、
正常終了を示す main() の戻り値 0 をその環境用の終了コードで成功の値にマップするのは
そのシステム向けの処理系の仕事になる。

成功・失敗の区別以外に興味がない限りCのコードを書くプログラマが気にする必要はない
と規格は想定している。
124デフォルトの名無しさん (ワッチョイ c123-wH+P)
垢版 |
2018/09/24(月) 13:59:06.82ID:KzNCIBHJ0
>>121
おまいWindowsでexe実行したとき必ず戻り値みてるか?
BATとかあるけどさ
2018/09/24(月) 17:18:25.80ID:1deJaFMg0
>>123
なるほど crt0あたりでmainから0が来た場合の本当の成功判定を処理してるってことですね。
ありがとうございました。
126さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
垢版 |
2018/10/14(日) 11:56:24.75ID:7zcwA4Ik0
せっかく上級者が集まっているんだし、評論でもやりましょう。
https://github.com/reactos/reactos/blob/master/win32ss/gdi/ntgdi/freetype.c
このソース、俺の担当なんだけど、ひまだったら
喧嘩上等で悪い所・直すべきところを全部指摘してくれ。頼むよ。
127デフォルトの名無しさん (アウウィフ FFeb-NsMu)
垢版 |
2018/10/14(日) 12:52:43.56ID:G4e8iFcgF
やっぱwindowsは糞だな
2018/10/14(日) 13:31:35.13ID:p/Li638e0
>>126
書き換えた所はどこ?
2018/10/14(日) 13:57:45.50ID:m0LzoO8+0
頑張ろうと思ったんだが、暇つぶしでやるには長すぎて挫折した。すまん。
2018/10/14(日) 13:58:41.27ID:b97yHnkE0
>>126
IntCharSetFromCodePage の for の中のひとつ目の if は削除して、for に入るまでに
if( uCodePage == 0 ) return DEFAULT_CHARSET;
をやる。
for に入るまでの if は 確率が高い順に並べる。

とか?
2018/10/14(日) 15:07:42.66ID:p/Li638e0
>>126
表面的になぞっただけで、意味は読んでいないから参考程度で。

L924-931、FW_*のenumに揃えられるのなら揃えた方がいい。あと、ベタで書くよりはループが良いかも。
L946関数他、InterLockを外部的に明示的に行っているけど、俺ならアクセス関数内に押し込む。
ただこれは以前揉めたから、他の流儀の奴もいるのかもしれない。
俺の考えとしては、enumやdefineする理由は、変更箇所を1ヶ所に留める(同期させずに済む)事だと考えているので、
外部的に明示的にInterLockをその都度行うのは、変更時に全ての場所を同期させる(同様に書き換える)必要があるという意味で悪手。
敢えてInterLockしていることを誇示したい等の他の理由がなければ、アクセス関数内に押し込む。
L2024,L2040,L2052,L2135、同じ事を4回書いてる。
おそらく全体的に低レベルまで全部触りに行く、ある意味Cに典型的なコードになっている。
嫌う人もいるとは思うが、俺ならこの4回をどうにか1つに纏めて抽象度を上げていく。
4つの*NameWを常に同時に使うものなら、普通はstructにする。
L2879とL2888で、FT_Done_GlyphとDPRINT1の順序が逆。
お互い干渉しないから問題なしなのだろうけど、可能なら順番は揃えた方がいい。
しかもL2926とL2934でも順番が逆なので、L2869-とL2923-ってコピペしてるだろこれ。
そういうのはマメにサブルーチンとして切り出すべし。でないと抽象度が上がらない。
L3567-L3581、同じ事を4回やってる。サブルーチンに切り出して xx=sub()の形で書くべし。
あと、リテラル(初期化構文)使えるのならリテラルで書いた方がすっきりすると思うが。
L5081-5112、悪いとは言わないが、どうにかならんのか?
失敗系の速度が大して必要ないなら、ReleaseAllResources()で if (NameInfo1!=0) ExFreePoolWithTagの様にして纏めるとか。
なおL5153、"WithTag"が無いバージョンを呼んでいるが大丈夫なのか?
可能であればL5162で関数切って2つの関数にした方がいいと思う。(リソース確保/失敗系と成功系を分ける)
L5889とかもそうだけど、おそらく全部のメンバを初期化してるだろ。だったら初期化構文使った方が見た目分かりやすい。
2018/10/14(日) 15:08:04.46ID:p/Li638e0
ただし、上記は「ソースを綺麗にする方法」であって、通常は速度は落ちるので注意。
酷い話、ベタで書きまくっている方が速いのも事実。
あと、既に言ったが、上記はなぞっただけであり、関数内しか見てないので注意のこと。
本当に問題なのは関数間であり、それはガチで時間をかけて読まないと分からないから、そこまではやる気無い。
ただ、この雰囲気なら、2割くらいの関数は整理(削除)出来るのではないかと思うけど。

自分でも気になっているところがあるのなら、それを先に言うべし。見るから。
2018/10/14(日) 15:31:36.33ID:7zcwA4Ik0
気になってることと言えば、TextOutでOPAQUEモードのときに背景を塗り潰さないといけないのだが、それを一個の長方形でいっぺんに出来ないかな。
2018/10/14(日) 15:35:42.20ID:p/Li638e0
>>133
とりえあず行番号と関数名を言え。
それとも、そのソースではない一般の話?
(Ctrl-Fでは6ヶ所引っかかるが)
2018/10/14(日) 15:44:21.77ID:p/Li638e0
ちなみに、これって、実際にフォントをレンダリングしているんだよな?2次ベジエ等で。
なら、OPAQUEの場合は先に塗りつぶしておいた上に描いた方が楽だと思うけど。
再帰等の条件に描画情報を使っていてそれが出来ない場合、反転でAND取ってORすれば昔のPSETにはなる。
(フォントの黒部分にもAlpha値があるのなら全面的に計算するだけだから、これではなさそうだし)
2018/10/14(日) 15:45:29.84ID:7zcwA4Ik0
>>134
GreExtTextOutW関数のL5847...L5954です。
2018/10/14(日) 15:47:47.17ID:7zcwA4Ik0
>実際にフォントをレンダリングしているんだよな?2次ベジエ等で。
FreeTypeというフォントレンダリングライブラリでビットマップとアウトライン曲線を取得しています。

>OPAQUEの場合は先に塗りつぶしておいた上に描いた方が楽だと思うけど。
そうしてます。
2018/10/14(日) 15:51:46.90ID:7zcwA4Ik0
>>130
それはないかな。すみません。
139さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
垢版 |
2018/10/14(日) 16:02:11.24ID:7zcwA4Ik0
>>131
WithTagの指摘、助かった。ありがとう。
https://github.com/reactos/reactos/pull/941
他の件については後程、検討する。
2018/10/14(日) 16:16:37.97ID:7zcwA4Ik0
4つの*NameWの件、修正してみた。ありがとう。
https://github.com/reactos/reactos/pull/942
2018/10/14(日) 16:28:37.53ID:p/Li638e0
>>137
> それを一個の長方形でいっぺんに出来ないかな。
L5853のfor文が気になっているのなら、多分このCountは文字数で、
英文の場合は文字種類間ごとにピッチを変えるからこうなっているのでは?(いわゆるプロポーショナルフォント)
1回の操作に纏めたければ、文字単位でビットマップを生成して重ねるのではなく、
あらかじめ全体のビットマップを作ってそこにレンダリングしていけばいいのだけど、
速度的には速くなりそうだけど、後々面倒だから文字単位にしているのではないかと。

ここを文字単位でしこしこやるのは、悪いことではないと俺は思うけど。
気になっているのは被る部分が2度レンダリングされるって事かな?
幅5pxで1px被ってたら20%高速化だから地味に大きいのも事実だけど。
書き換えたいのなら後述参照。

なお、本筋とは異なるが、L5885-5887, L5926, L5938は正常系でもDPRINTしてるが大丈夫なのか?
DPRINT自体がリリースビルドでは消される仕様なら問題ないが。

>>139
正直なところ、指摘は参考に留めて、必要ない限りあまりいじらない方が良いとは思う。
これは昔の「動いているコードを触るな」であり、今風の「積極的にリファクタしろ」ではないが、
リファクタはデグレードをガッツリ検出出来る環境があればこそであって、
例えばchromeとかはそれをガチガチにやっているから出来るのであって、
検証環境のサポート無しなら、バグだと分かったところだけ修正し、そのついでに書き換える程度の方がいいと思うよ。

それで、該当部分を書き換えたいのなら、俺なら以下の手順でやる。(自己でデグレードチェックをする)
1. 対象部分、5847-5954を関数に切り出す。
2. その関数と全く同じ出力を生成する新関数(書き換えて1回でレンダリングするもの、おそらく20%程高速)を作る。
3. 両方とも呼び出す形でデバッグビルドし、結果を常に比較する状態でしばらく動かす。
 具体的には、旧関数出力と新関数出力のビットマップを全比較する。
 フォントのレンダリングなんてものすごい回数行われるので、バグっているようなら大抵これで検出出来る。
高速化は結構すると思うから、書き換える意味はあるとも思うけど。やるなら頑張れ。
2018/10/14(日) 19:15:26.67ID:p/Li638e0
>>139
はえーよ

>>140
第一段階としてはそれで良い。

(以下は改変後の行番号として)
ただ、オブジェクト指向的にはL2033-2036の中身をいちいち見せてNeededに足すのは悪手で、
可能なら AllLengthというプロパティを作りたいところ。
Cなら関数FONT_NAMES_get_all_length()とかで「中身を知らなくても全部の長さが分かる」様にして疎結合化する。
(後々fontNamesにメンバが追加されても struct FONT_NAMES の変更だけで済むようになる)

それで、L2125-L2141でご丁寧に全部Otm(の後ろ)にコピーしてるだろ。
これだと、多分、本来はOtm内に FONT_NAMES 構造体を持ち、そこに構造体のコピーで済むように書けるはず。
具体的には、

Otm->FontNames = FontNames; // --- (α)

みたいな。
2018/10/14(日) 19:15:52.58ID:p/Li638e0
ただこれ、データ埋め込みだから Otm->otmFamilyName等はオフセットで管理し、
不要なUNICODE_STRING構造体部分は破棄して文字列実体だけコピーするケチケチ作戦か?
なら、普通は文字列実体のコピー関数をメンバ関数として用意する。Cなら、

char* UNICODE_STRING_copy_string(UNICODE_STRING* ustr, char* Cp){ // --- (β)、一応thisを第1引数にした
wcscpy((WCHAR*) Cp, ustr.Buffer);
return Cp + ustr.Length + sizeof(WCHAR);
}

そしてL2124-2126を

Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm);
Cp = UNICODE_STRING_copy_string(FamilyNameW, Cp); // --- (γ)

として、実装をはがしていく。(疎結合化する)
これで UNICODE_STRING 内にメンバ Buffer と Length があることを知らなくてもコピー出来るようになった。
同様に、Otm内に直接FontNames(または文字列実体だけコピー済みのchar*)を持つようにして、
FontNamesと同じ型を使い回せるようにすれば、もっと記述は少なくて済むし、疎結合化していく。(α)

ただし、ここら辺がLinusが嫌う、C++が逆に結合していく部分であって、
コード上の静的コールグラフでは疎結合化するが、型を通して知識的に密結合してしまう、というところ。
具体的には、FontNamesで綺麗に書こうとすれば OUTLINETEXTMETRICW に FONT_NAMES を持たせるべきだが、
これをやると、OUTLINETEXTMETRICWを使う人は全員FONT_NAMES構造体を知っていけないといけなくなる。
今のところ FONT_NAMES 構造体はオレオレ構造体であり、これは避けるべきだ。
逆に、UNICODE_STRINGはおそらく全体で使われている構造体なので、
(β)の関数を用意したら他でも色々使い回せ、全体的に記述を減らせるはず。
だから、次の手としては(β)+(γ)で記述を減らすべきだ。
ただし、もし仮に、型 OUTLINETEXTMETRICW を使うときには常に FONT_NAMES 構造体を知っているべきだ、というのであれば、
(α)の方向に変更していった方が最終的には綺麗になる。

てゆーか、頭大文字でも変数なのかー、まあそういうルールならそれでいいが。
2018/10/14(日) 19:38:11.68ID:p/Li638e0
>>143訂正
× .
○ ->
見れば分かるとは思うが。
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況