2022-08-11 読書メモ
文字列を示す "abc"、_T("abc\")、L"abc" は全て意味が違う!(UsefullCode.net)
まず自身の認識。TCHAR
は UNICODE ビルドする/しないに応じて WCHAR
/ char
のどちらにもなり得るプレースホルダ的なもの。
‘_T("<文字列>")‘ も同様で、UNICODE ビルド時は UNICODE 文字列として、非UNICODE ビルド時は Shift-JIS 等として扱われるそうだ。
ワイド文字
用語
- ANSI C は標準でワイド文字をサポートしている
- ワイド文字: 1文字表現するのに2バイト用いるもの
- マルチバイト文字: 1バイト以上の文字のこと
L プレフィクス
文字列の前に付加することでコンパイラにワイド文字列として扱うよう指示する。
LinuC レベル1-101
cut コマンドのデリミタ指定
デフォルトでタブ区切りだが、タブ区切りを明示指定する場合は -d $'\t'
のように指定する。Ctrl + V
の後にタブキーを押しても良いが、-d $'\t'
のほうがスクリプトとしては見やすい。しかしこれなんていう表記方法なんだろう。
fmt と fold
fold が指定桁数で問答無用で折り返すのに対し、fmt は単語境界等を考慮する。
C++ リテラル "あいうえお" のエンコード
C/C++ が何も分からないので、細かいことを無理に理解しようとせずいろいろやってみたい今日この頃。実行環境は Visual Studio 2022
。
char s[] = "あいうえお" のエンコード?
#include <iostream> using namespace std; int main() { char s[] = "あいうえお"; cout << s << endl; }
として実行すると、デバッグコンソールに あいうえお
と表示される。問題はこのときのコードポイントが 932 (ANSI/OEM - Japanese Shift JIS)
だということ。特に明示的にエンコードしていないが、どうやら Shift JIS エンコードされているらしい。
"あいうえお" のサイズ
Visual Studio 上で "あいうえお"
にマウスオーバーすると (const char [11])"あいうえお"
と出る。内部的に何らかのエンコーディングが施されていて、(文字列終端を除けば) 1文字あたり2バイト使っている計算。
"あいうえお" を1byteずつ表示させてみる
#include <stdio.h> #include <iostream> using namespace std; int main() { char s[] = "あいうえお"; cout << s << endl; for (int k = 0; k < sizeof s; k++) { printf("%X ", (unsigned char)s[k]); } }
実行結果
あいうえお 82 A0 82 A2 82 A4 82 A6 82 A8 0
文字コード表 シフトJIS(Shift_JIS) を見て確認。Shift JIS としてエンコードされており、ビッグエンディアンで格納されていることがわかる。
まとめ
正確なところはよくわからないが、Visual Studio のコンパイラ設定?として非ASCII 文字リテラルを環境に応じていい感じにエンコードするようにしてくれているのかもしれない。
INT_MAX (DRAFT)
概要
ε-N論法について - Qiita を 論法を勉強するために読んでいたのだけれど、例として C のコードで表現されている部分が理解できなかったのでメモ。C 言語は現状入門サイトを読んだくらい…。
float a[ INT_MAX ] (Win10, VS2022)
まずこの時点で目玉が飛び出そうになる。ものすごく巨大な配列を宣言しているように見えるが…。
手元に Visual Stdio 2022 Community をインストールし、C++ コンソールプロジェクトを作成して書いてみる。
まず、INT_MAX
が定義されていないのでエラーになった。C言語入門 - 整数型(char型 int型)の最大値と最小値 - limits.h - Webkaru を読むと INT_MAX
は limits.h
に定義されているようなので include する。
#include <stdio.h> #include <limits.h> int main(void) { float a[ INT_MAX ]; return 0; }
array is too large
のエラーが出る。無理やりビルドすると error C2148: total size of array must not exceed 0x7fffffff bytes
と出る。やっぱりちょっと無茶な配列確保をしているように見えるが…。
INT_MAX はいくつか
エラーを解釈するため、順番に確認してく。まず INT_MAX
がいくつなのか。
int main(void) { printf("INT_MAX = %d\n", INT_MAX); return 0; } // INT_MAX = 2147483647
2,147,483,647 (232 - 1) のようだ。これは 0x7fffffff に等しい。
sizeof_t(float) はいくつか
配列サイズが 型のサイズ
* 要素数
で決まるならば、次に float
のサイズが気になるところ。
int main(void) { printf("sizeof(float) = %d\n", sizeof(float)); return 0; } // sizeof(float) = 4
sizeof(float) = 4
らしい。
なお書式指定子に %d
を指定するのはダメなようで、下記のような警告が出ている。
Code | Description | |
---|---|---|
Warning | C6328 | Size mismatch: 'unsigned int64' passed as Param(2) when 'int' is required in call to 'printf'. |
Warning | C4477 | 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'size_t' |
size_t 型を printf するための書式指定子は何か
いろいろググると Visual Studio C コンパイラが C の標準規格?にどこまで対応しているか?みたいな話が出てきてよくわからなくなってきたのだが、printfとsize_t型 - yohhoyの日記 を読むととりあえず %zd
のように指定すると良いようで、警告は消えた。
配列サイズが 0x7fffffff bytes 未満になるように宣言してみる
以上より、INT_MAX
= 0x7fffffff
であること、sizeof(float)
= 4
であることが分かった。
(INT_MAX / 4) * 4 = (2,147,483,647 / 4) * 4) = 2,147,483,644 = 0x7ffffffc < 0x7fffffff
だから、要素数を INT_MAX / 4
にすればエラーは出ないのではないか。
int main(void) { float a[ INT_MAX / sizeof(float) ]; return 0; } // fatal error C1126: automatic allocation exceeds 2G
error C2148: total size of array must not exceed 0x7fffffff bytes
は出なくなったが、代わりに fatal error C1126: automatic allocation exceeds 2G
が出た。
automatic allocation exceeds 2G エラーが出ないサイズを探す
INT_MAX / 4
= 536,870,911
から2分探索で減らしていきながら確かめた。
int main(void) { //--- fatal error C1126: automatic allocation exceeds 2G // float a[ INT_MAX / sizeof(float) ]; //--- fatal error C1126: automatic allocation exceeds 2G // float a[511999993]; //--- Stack overflow float a[511999992]; return 0; }
要素数 511,999,992
のときにコンパイルエラーは出なくなったが、今度は実行時に Stack overflow
が発生した。
Stack overflow が出ないサイズを探す
同じように2分探索で減らしていきながら確かめた。
int main(void) { //--- fatal error C1126: automatic allocation exceeds 2G // float a[ INT_MAX / sizeof(float) ]; //--- fatal error C1126: automatic allocation exceeds 2G // float a[511999993]; //--- Stack overflow // float a[511999992]; float a[ 257175 ]; //--- 明確な境界は無いが大体このあたり return 0; }
同じ値でも Stack overflow が起きるときと起きないときがあるものの、257,000
あたりから発生する様子。sizeof(float)
= 4
をかけると 1,028,000
となることから、大体 1MB あたりに上限がありそうだ。
Stack サイズを増やす
"visualc stacksize increase" とかでググっていたところ、/STACK (Stack allocations) | Microsoft Docs を見つけた。
The /STACK linker option sets the size of the stack in bytes. Use this option only when you build an .exe file.
The reserve value specifies the total stack allocation in virtual memory. For ARM64, x86, and x64 machines, the default stack size is 1 MB.
やはりスタックサイズはデフォルト 1MB らしい。そしてこの値は project's Property Pages
から変更できると書かれている。
- Visual Studio メニューバーから
Project
→<プロジェクト名> Properties
とクリックすると<プロジェクト名> Property Pages
が開く Configuration Properties
→Linker
→System
と進むStack Reseve Size
を大きな値にする。今回はINT_MAX
と同じ2147483647
としてみた
Stack サイズを増やしてから再実行
int main(void) { //--- fatal error C1126: automatic allocation exceeds 2G // float a[ INT_MAX / sizeof(float) ]; //--- fatal error C1126: automatic allocation exceeds 2G // float a[511999993]; //--- 成功 float a[511999992]; return 0; }
511999992
指定時はデフォルトでは Stack overflow となったが、Stack サイズを増やしたところ成功。511999993
のときは変わらず fatal error C1126: automatic allocation exceeds 2G
が出る。こちらは Stack サイズとはまた別の制限なのかもしれない。
結論: float 配列 をローカル宣言する場合のサイズ上限 (VS2022)
Windows + Visual Studio 2022 環境において、Stack Reseve Size
を十分大きく取った場合、float 配列は要素数 511,999,992 までならローカル変数として宣言できる。
float a[ INT_MAX ] (Ubuntu 20.04.3 LTS)
上記では Visual Studion 2022 上でゴリゴリ調べていたが、Linux だとどうなのだろう?と思い立った。
$ cat ipsd.c #include <limits.h> #include <stdio.h> int main(void) { float a[ 2096110 ]; return 0; } $ gcc ipsd.c && ./a.out $ gcc ipsd.c && ./a.out Segmentation fault (core dumped) $ gcc ipsd.c && ./a.out Segmentation fault (core dumped) $ gcc ipsd.c && ./a.out Segmentation fault (core dumped) $ $ gcc ipsd.c && ./a.out $ gcc ipsd.c && ./a.out Segmentation fault (core dumped) $ gcc ipsd.c && ./a.out $ gcc ipsd.c && ./a.out $ gcc ipsd.c && ./a.out
やはり安定はしないが、要素数 2096110
あたりが上限に見える。VS2022 に比べると大きく見える。
Linux のスタックサイズ上限
Linux Stack Sizes - Stack Overflow を見ると Linux のスタックサイズ上限は ulimit -s
で確認/設定できるとのこと。自身の環境も 8192
だった。
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31289 max locked memory (kbytes, -l) 65536 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 31289 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
スタックサイズを増やしてから再実行
$ ulimit -s unlimited $ $ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31289 max locked memory (kbytes, -l) 65536 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) unlimited cpu time (seconds, -t) unlimited max user processes (-u) 31289 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited $ $ cat ipsd.c #include <limits.h> #include <stdio.h> int main(void) { float a[ INT_MAX ]; return 0; } $ gcc ipsd.c && ./a.out $ time ./a.out real 0m9.900s user 0m0.380s sys 0m1.829s
ということで、float a[ INT_MAX ]
でも全く問題なく実行できた。
ちなみに実行環境は ESXi 上に建てた Ubuntu VM で、割り当てメモリは 8G。上記実行中に top
を見ると メモリの used
が 7810 MiB
まで上昇していた。INT_MAX * 4
= 8589934588
なので、おおよそ計算は合うことになる。
結論: Linux での float a[ INT_MAX ]
物理メモリが十分あって、ulimit -s unlimited
していれば問題無し。元記事の筆者の方ももしかすると Linux 環境で試されていたのかもしれない。
休憩
float a[ INT_MAX ]
を解釈するだけですごく大変だった。続きはまた今度。
はてなブログで Tex 記法が崩れる問題
概要
数学の復習をしたい → はてなブログは数式が書けるはずだ → ググってみるとどうやら [tex: ]
という記法を使うらしい。→ うまく表示されないよ!という話。
結論: <div></div> で囲むとうまくいく。
うまくいく場合
例えばこのように書いてみる: [tex: ∀ε > 0, ∃N∈\mathbb{N} ]
上記のように問題なく表示されている。
このときページソースはこの形。
<script type="math/tex" id="MathJax-Element-1"> ∀ε > 0, ∃N∈\mathbb{N} </script>
うまくいかない場合
しかしこのように書いてみると: [tex: | a_n - \alpha | < ε ]
上記のようにうまくいかない。
このときページソースはこの形。<
がなぜか <
と HTML エスケープされてしまっている。
<script type="math/tex" id="MathJax-Element-2"> | a_n - \alpha | < ε </script>
div で囲うと大丈夫
はてなブログで数式(Markdown) - エフアンダーバー を読んで回避策を見つけることができた。<div>
で囲むとよいらしい。
<div style="margin: 1em">[tex: | a_n - \alpha | < ε ]</div>
正常に表示された。
あらためて
書きたかったのは 論法。
<div style="padding: 1em"> [tex: \displaystyle { ∀ε > 0, ∃N∈\mathbb{N} \ \ s.t. \ \ ∀n ∈ \mathbb{N},n \geq N \Rightarrow | a_n - \alpha | < ε }] </div>
うまく出力できた。これで数学関係のメモもブログに書けるだろうか。
そもそも Tex
記法がさっぱりなのでそれも勉強しないといけない。
LinuC 1-101 勉強
07/23
man のセクション番号
が覚えられないので語呂合わせを考えてみる。
ユーザのシステムをライブでデバイス設定するゲーム
セクション番号 | 説明 |
---|---|
1 | ユーザーコマンド |
2 | システムコール |
3 | ライブラリ |
4 | デバイスファイル |
5 | 設定ファイル |
6 | ゲーム |
man コマンドを叩ける環境が手元にない。仮想マシンを立てるべきか。
man コマンドオプション
-k (--apropos)
-k, --apropos Equivalent to apropos. Search the short manual page descriptions for keywords and display any matches. See apropos(1) for details.
NAME
apropos - search the manual page names and descriptions
DESCRIPTION
Each manual page has a short description available within it.
apropos searches the descriptions for instances of keyword.
search A for B
: B を求めて A を調べる,探す (引用)
page names / descriptions にキーワードを 含む ものを検索する。apropos
は "適切に","折よく" といった意味。
$ man -k cron cron (8) - daemon to execute scheduled commands (Vixie Cron) crontab (1) - maintain crontab files for individual users (Vixie Cron) crontab (5) - tables for driving cron keep-one-running (1) - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg) run-one (1) - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg) run-one-constantly (1) - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg) run-one-until-failure (1) - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg) run-one-until-success (1) - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg) run-this-one (1) - run just one instance at a time of some command and unique set of arguments (useful for cronjobs, eg)
-f (--whatis)
-f, --whatis Equivalent to whatis. Display a short description from the manual page, if available. See whatis(1) for details.
NAME whatis - display one-line manual page descriptions DESCRIPTION Each manual page has a short description available within it. whatis searches the manual page names and displays the manual page descriptions of any name matched.
$ man --whatis cron cron (8) - daemon to execute scheduled commands (Vixie Cron) $ man --whatis crontab crontab (5) - tables for driving cron crontab (1) - maintain crontab files for individual users (Vixie Cron)
-k
, apropos
と違い、page name がキーワードに 一致 するものを検索する。
ESXi 環境で遊びたい
前回までのあらすじ
Dell の G5 5000 という PC を昔買った.無駄にメモリが 64 GB もあるし単体で使うのはもったいないと,VMware vSphere Hypervisor (ESXi) をインストールしたのだった.それが楽しい地獄の始まりだった.
最初に悟ったのは ESXi はハードウェアとセットで買うものだなということ.そこらの適当な SSD や NIC だとインストール時点でさっぱり認識しない.仕事で触るものは HP サーバなんかと一緒にライセンス購入しているのでそのあたり気にしたことがなかった.
その後ググりまくって Intel チップの NIC を取り付けたり ESXi のバージョンを下げたりして最終的にやっと ESXi 6.7 Update 1 のインストールに成功したのだった.
旧環境 (Hyper-V) から Windows VM を引っ越し,ライセンス認証して一息ついた後,「これだとせっかくの GeForce RTX 2070 が VM で生かせないじゃないか」と気づいた.そして PCI パススルーという概念を知り,さらなる地獄に突入していくのだった.
最終的に疲れ切ってしまい,結局今は 13 年もののデスクトップ PC をメインに使っている.
やりたいことを整理する
さてこの ESXi 環境で自分は何がしたいのか
自然,PCI パススルーが要件になってくる.
あるべき形と遊び心
身も蓋もない結論から言うと,G5 5000 はそこそこ性能のいいゲーミング PC なのだから素直にスタンドアロンで使って,ESXi で遊びたいのであれば別途それ向きのハードウェアを買えばいい.それが最も自然な形.
だがお財布は厳しい.それが現実.それにせっかくの自宅環境,会社ではとてもできない攻めた構成をするチャンス.楽しい地獄に行こうじゃないか.
ESXi ホスト現状確認
ハードウェア情報
ESXi shell からコマンドで確認していく.
#--- ESXi 情報 [root@ESXI-01:~] vim-cmd hostsvc/hostsummary | grep -e fullName fullName = "VMware ESXi 6.7.0 build-10302608",
#--- PC モデル [root@ESXI-01:~] esxcli hardware platform get Platform Information UUID: ***** Product Name: G5 5000 Vendor Name: Dell Inc. Serial Number: ***** Enclosure Serial Number: ***** BIOS Asset Tag: IPMI Supported: false
#--- CPU 情報 [root@ESXI-01:~] vim-cmd hostsvc/hostsummary | grep -e cpuModel cpuModel = "Intel(R) Core(TM) i7-10700KF CPU @ 3.80GHz", [root@ESXI-01:~] esxcli hardware cpu global get CPU Packages: 1 CPU Cores: 8 CPU Threads: 16 Hyperthreading Active: true Hyperthreading Supported: true Hyperthreading Enabled: true HV Support: 3 HV Replay Capable: false HV Replay Disabled Reasons: incompatible CPU
#--- メモリ 情報 [root@ESXI-01:~] esxcli hardware memory get Physical Memory: 68482859008 Bytes Reliable Memory: 0 Bytes
#--- SSD 情報 [root@ESXI-01:~] esxcli storage core device uidmap list #--- SanDisk SATA SSD 240 GB t10.ATA_____SanDisk_SSD_PLUS_240GB__________________20248N442803________ Primary UID: t10.ATA_____SanDisk_SSD_PLUS_240GB__________________20248N442803________ Alternative Primary UIDs: Legacy UID: vml.010000000032303234384e343432383033202020202020202053616e446973 Alternative Legacy UIDs: #--- Samsung NVMe SSD 512GB (ESXi システムディスク) eui.353039304e8771560025384600000001 Primary UID: eui.353039304e8771560025384600000001 Alternative Primary UIDs: t10.NVMe____PM991_NVMe_Samsung_512GB______________________S509NF0N87715600000001 Legacy UID: vml.0100000000333533305f333933305f344538375f373135365f303032355f333834365f303030305f303030312e504d3939 Alternative Legacy UIDs: vml.0100000000202020202020533530394e46304e383737313536504d39393120 #--- SanDisk SATA SSD 240 GB t10.ATA_____SanDisk_SSD_PLUS_240GB__________________20248N446313________ Primary UID: t10.ATA_____SanDisk_SSD_PLUS_240GB__________________20248N446313________ Alternative Primary UIDs: Legacy UID: vml.010000000032303234384e343436333133202020202020202053616e446973 Alternative Legacy UIDs:
RDM ディスク情報
SATA 接続の SSD 2枚を VM 向けにパススルーしている.Maps to:
の vml. ...
が上記 esxcli storage core device uidmap list
の Legacy UID と対応している様子。
[root@ESXI-01:~] vmkfstools -q /vmfs/volumes/datastore1/RDM/SanDisk_SSD_PLUS_240GB_20248N442803.vmdk Disk /vmfs/volumes/datastore1/RDM/SanDisk_SSD_PLUS_240GB_20248N442803.vmdk is a Passthrough Raw Device Mapping Maps to: vml.010000000032303234384e343432383033202020202020202053616e446973 [root@ESXI-01:~] [root@ESXI-01:~] vmkfstools -q /vmfs/volumes/datastore1/RDM/SanDisk_SSD_PLUS_240GB_20248N446313.vmdk Disk /vmfs/volumes/datastore1/RDM/SanDisk_SSD_PLUS_240GB_20248N446313.vmdk is a Passthrough Raw Device Mapping Maps to: vml.010000000032303234384e343436333133202020202020202053616e446973 [root@ESXI-01:~]
デバイスパススルー状況
Address | Description | Passthrough | メモ |
---|---|---|---|
0000:01:00.3 | nVidia Corporation Serial bus controller | Active | VM 用 GPU |
0000:01:00.2 | nVidia Corporation USB controller | Active | VM 用 GPU |
0000:01:00.1 | nVidia Corporation Audio device | Active | VM 用 GPU |
0000:01:00.0 | nVidia Corporation VGA compatible controller | Active | VM 用 GPU |
0000:03:00.0 | Realtek Semiconductor Co., Ltd. Ethernet controller | Active | VM 用 LANポート |
0000:05:00.1 | Intel Corporation 82575EB Gigabit Network Connection | Disabled | ※未使用 |
0000:05:00.0 | Intel Corporation 82575EB Gigabit Network Connection | Disabled | ESXi 管理アクセス用 |
Win10 VM 現状確認
PCI device 設定
PCI device 番号 | デバイス名 |
---|---|
PCI device 1 | |
PCI device 2 | |
PCI device 3 | |
PCI device 4 | |
PCI device 5 |
モニタ出力
GPU パススルーしているので,RTX 2070 から HDMI ケーブルをモニタにつなげれば映る.再起動時やスリープ時に問題あり.
入力デバイス
オンボード USB ポートをパススルーできないので,マウスやキーボードを差せない.つまり直接動かす手立てがない.
音声出力
入力デバイスと同様,オンボードの音声入出力端子をパススルーできないため出力できない.
次にやること
- USB カードを追加してパススルーし,USBマウス・キーボードを接続できるようにする
- USB サウンドカードを接続し,外部スピーカーと接続する
まずはここからだ.