2019年1月28日月曜日

.bssセクションのグローバル変数の初期化について

こんにちは、ふじかーです。

先日現場で グローバル変数の初期化 が話題に上がりました。

「このグローバル変数で判定してますね。値、何が入ってるんだろ」
「定義時には特に初期値入れてないですね」
「あら、判定までずっと値入れてないですね。じゃ値は0ですか」
「なんか不定値になることありませんでしたっけ?」
「必ず0初期化されるんじゃなかったですかね?」

昔調べた気がするけど、正確にはどうだったか・・
と曖昧になっていたので、少し確認しなおしました。

セクション


プログラムはメモリに配置されて実行されるわけですが、メモリ上には
プログラム内の「機械語」や「変数」「定数」など、各種用途ごとに分かれて配置されています。

その単位のことをセクションといいますが
今回のグローバル変数などは『.bss セクション』という領域に格納されます。

.bssセクションに格納される変数の種類は

・初期値 なし の グローバル変数
・初期値が 0 の グローバル変数
・初期値 なし の 静的(=static)なローカル変数
・初期値が 0 の 静的(=static)なローカル変数

となっています。

この.bss領域は「全て0初期化されているべし」とC言語の規約で規定されているため
プログラム実行前に、領域を確保して丸ごと0初期化されるようです。

wikipedia
通常、bssセクションに割り当てられたメモリは
プログラムローダーがプログラムをロードするときに初期化する。
main() が実行されるより前に
Cランタイムシステムがbssセクションにマップされたメモリ領域をゼロで初期化する。

ちなみに、初期値あり(0以外) のグローバル変数や静的ローカル変数は?というと
『.dataセクション』 という領域に格納されます。
プログラム実行前に、領域を確保して値を格納していきます。

また、「const」がつけられる定数が格納されるのは
『.rodataセクション』 という領域です。

さらに関数などプログラムの機械語そのものは
『.textセクション』 という領域です。


メジャーなのはそのあたりですが、
ビルド後の実行ファイルの各セクションがどのように配置されるか、
下記のコマンドで確認することができます。

>objdump -h a.exe



落とし穴


初めの話に戻り、.bssは 言語の仕様として0初期化される と決まっているので

「じゃあグローバル変数は自動的に『起動時0初期化処理』されてるものとして
 使うときも特に初期化せずに使えば良いね」

と考えられるかというと、そうでも無いようです。


場合によって、例えば組み込み機器などで

「電源投入からプログラム起動までの時間を極力短くしたい。
 メモリの初期化時間ですら、可能なかぎり限界まで削りたい」

というシーンでは、

やろうと思えばこの『起動時0初期化処理』を省くことができるようで、
そうすると実行時のグローバル変数には「不定値」が入っていたりするとの事。

やはり変数を使う前には、明示的に値を入れて初期化してから使う方がよさそうです。
見つけにくいバグや、不要な不安やトラブルを避けられますもんね。
今後実装する時やレビューする際は、気を付けたいと思います。

※関連記事:メモリのセクション内の配置を確認してみた

2019年1月19日土曜日

git コマンド チートシート。これだけは覚えておきたい!



こんにちは。よっしーです。

複数人のプロジェクトに参加すると、

もれなくついてくるのが、バージョン管理システムです。


少し前までは svn をよく使っていたのですが、

時代の流れもあり、最近では git を使うようになりました。


現在は、開発環境がLinuxなので、GUIツールは使わず、

端末上で git コマンドを直接叩いて処理しています。


せっかくなので、これだけ覚えていれば一通りの作業は出来ますよ。

というものを自分用の備忘録として以下にまとめます。




1.git リポジトリを取得

git clone https://リポジトリアドレス

この場合、デフォルトで master ブランチが取得されることになるので、
master 以外のブランチを直接取得する場合は、以下のブランチ指定で clone する。

git clone -b ブランチ名 https://リポジトリアドレス



2.git の設定

ユーザ名とEメールの設定

git config --global user.name ユーザ名
git config --global user.email Eメールアドレス

(この設定をしないと git へ commit 出来ない。)

git commit する時、パーミッション変更を無視する設定

git config core.filemode false



3.commit 関連

変更内容をaddする

git add コミットしたいファイル

全ての変更内容を add する場合は以下。

git add -A

変更ファイルなどの一覧を確認

git status

変更内容をコミット

git commit -m コミットログ

リポジトリへ反映

git push origin ブランチ名



4.差分確認

add する前に変更点を見る

git diff

add した後に変更点を見る

git diff --cached

commit した後に変更点を見る

git diff HEAD^



5.コミットログ確認

ログを確認

git log

ログを差分付きで確認

git log -p



6.ブランチ操作

変更の取り消し(追加されたファイルは残る)

git checkout .

ブランチ切り替え

git checkout -b ブランチ名 origin/ブランチ名



7.コミットログ

git commit する際のコミットログ(変更履歴)ですが、

業界的には「明確で簡潔に英語で!」というのがスタンダードになりつつあります。

英語が苦手な私は、これを考えるのに、なかなか時間がかかったりします。


そういったコミットログを考えるのに困っている人のため、

コミットログの例文をまとめているサイトもあります。

かなり、ここには助けられていますので、同じような人は参考にしてみてください。




ではまた~。

2019年1月12日土曜日

Visual Studio Code で C++ と Python をデバッグする


こんにちは、ふじかーです。

明けましておめでとうございます。本年もよろしくお願いします。

さて、こないだ下記の記事で VS Code でC言語デバッグできるようにしたんですが
Visual Studio Code でC言語をステップ実行

現場で C++ を扱う可能性が出てきたので、
そちらも VS Code で動かせるようにしたいと思います。

あと、ついでに Python も動かせるようにしたいと思います。

C++_デバッグ環境作成の流れ


    基本的に前回の C言語環境 作成時と同じ流れです。
    ファイル名や設定が少し異なるくらい。
    → ここまでは C言語環境 作成時と全く同じ手順ですので
      前回の記事にリンクしています。実施済みの場合とばしてください。



    C++_作業場所、test.cppの準備


    C言語の時と同じく、適当にHelloWorldソースを用意します。

    #include <iostream>
    
    int main() {
        std::cout << "Hello, world!" << std::endl;
        return 0;
    }
    

    これを作業フォルダに保存しておきます。ここでは D:\test\cpp\test.cpp としました。

    またこの作業フォルダを、VS Code のメニューから開いておきましょう。
    ・メニュー → フォルダーを開く → D:\test\cpp



    C++_デバッグの為の設定

    • ビルドタスクの設定(tasks.json)
    修正したソースコードをビルドするための設定を行います。
    ほぼC言語の時と同じで、コマンド行が下記のように異なるだけなので
        C言語・・・ "gcc -g -O0 -o a.exe test.c"
        C++   ・・・ "g++ -g -O0 -o a.exe test.cpp"

    C言語の時の tasks.json があるならファイルコピペして
    コマンド行だけ編集してもOKです。

     ・フォルダーを開いている状態で Ctrl+Shift+B
     ・「実行するビルドタスクがありません。ビルドタスクを構成する」というメッセージが出るのでクリック
     ・「テンプレートからtask.jsonを作成する」というメッセージが出るのでクリック
     ・表示された候補の中から「Others 任意の外部コマンドを実行する例」を選択
      → 作業フォルダ内に「.vscode/tasks.json」ファイルが自動生成され、画面に表示される




     ・表示された task.json の
    "command": "echo Hello"
    
      を削除して、下記を挿入
    "command": "g++ -g -O0 -o a.exe test.cpp",
    "problemMatcher": "$tsc", 
    "group": {
        "kind": "build",
        "isDefault": true
    }
    
     ・Ctrl+S で保存しておく


    • デバッグ環境の設定(launch.json)
     デバッグに必要な設定を行います。こちらはC言語の時と完全に同じなので、
    C言語の時の launch.json があるならファイルコピペでもOKです。

     ・画面左のデバッグアイコンを押下
     ・デバッグの開始アイコン(再生マーク)を押下
     ・表示された候補の中から「C++(GDB/LLDB)」を選択
      → 作業フォルダ内に「.vscode/launch.json」ファイルが自動生成され、画面に表示される




     ・表示された launch.json の
    "program": "enter program name, for example ${workspaceFolder}/a.exe",
    "miDebuggerPath": "/path/to/gdb",
    
      を削除して、下記を挿入
    "program": "${workspaceRoot}/a.exe",
    "miDebuggerPath": "c:\\mingw\\bin\\gdb.exe",
    
     ・Ctrl+S で保存しておく



    C++_デバッグ開始!


     ・試したいコードをmain関数に記載し、リビルドは Ctrl+Shift+B
     ・ブレークポイントをセットしてF5でデバッグ開始、F10でステップ実行



    Python_デバッグ環境作成の流れ


      お次は Python です。
        →  ここも同じ手順ですので、実施済みの場合とばしてください。



        Python3のインストール


        パソコンにまだPythonを入れていない場合、
        下記サイトに従ってインストールしておきます。








        Python_拡張機能をインストール


        C言語の時と同じく、Python開発用の拡張機能もインストールしておきます。
         ・画面左の 拡張機能(Extensions)ボタン を押して「python」で検索 → インストール → VS Codeを再起動






        Python_作業場所、test.pyの準備


        C言語の時と同じく、適当にHelloWorldソースを用意します。

        a = "Hello World!"
        print(a)
        

        これを作業フォルダに保存しておきます。ここでは D:\test\python\test.py としました。

        またこの作業フォルダを、VS Code のメニューから開いておきましょう。
        ・メニュー → フォルダーを開く → D:\test\python



        Python_デバッグ開始!




         ・ブレークポイントをセットしてF5でデバッグ開始、F10でステップ実行


        Pythonはインタープリタ言語なのでビルドとか必要ありません。お手軽。
        ただこのとき、こんなエラーメッセージが出る事があります。



         これはPythonのLinter(構文チェッカ)が入ってないよ、というエラーのようなので
         インストールしておきましょう。



        2018年12月28日金曜日

        Wi-Fiのややこしい規格名称にさようなら。来年からはわかりやすい呼称になるぞ!



        こんにちは、よっしーです。

        さてみなさん。世の中にかなり浸透しているWi-Fiですが、

        通信規格の種類などを把握した上で使っていますか?

        代表的なものを挙げると、以下のようなものがあります。


        IEEE 802.11a

        IEEE 802.11b

        IEEE 802.11g

        IEEE 802.11n

        IEEE 802.11ac


        下へ行くほど新しい規格となり、

        それぞれの規格によって、

        通信速度、周波数、電波干渉などの特徴が異なります。


        自分が持っているスマホと無線LANが、どの規格に対応しているか。

        ぐらいは知っておくべきですよね。


        せっかく最新のスマホに買い替えても、

        使っている無線LANが、古い規格にしか対応していない場合、

        無線LAN側に合わせた低レベルの通信規格が使われてしまい、

        スマホの無線性能を「活かせない」ということになってしまいます。


        ただ、この規格名称が割と素人泣かせというか、

        abc順に並んでいるならまだしも、暗号みたいで覚えにくいし、

        何がどれだか、とてもわかりにくいですよね。。。


        さらに今後、通信速度やスループットがぐっと向上した、

        「IEEE 802.11ax」という規格も出てきます。


        混沌としてきましたね。。。


        で、ここからが本題なのですが、

        この「IEEE 802.11ax」は「Wi-Fi6」という名前になります。

        あら、ずいぶんと覚えやすい名前になりましたね。


        で、さらにいうと、

        「IEEE 802.11ac」→ 「Wi-Fi5」

        「IEEE 802.11n」→ 「Wi-Fi4」

        という名前になるようで、

        各種機器の表現も統一されていくようです。


        こうなると、IEEE 802.11g が Wi-Fi3 になるのかな?

        と思ったのですが、IEEE 802.11g 以前の規格は、

        とくに名称は付けられていないようです。


        802.11a/b/g などは使っている人も少なくなっているので、

        主流なもの以外は切り捨てられているのかもしれませんね。


        ということで、来年、平成が終わり元号変わりますが、

        Wi-Fiも新しい元年が始まるといってもいいかもしれません。


        ではまた~。

        2018年12月22日土曜日

        MATCH? INDEX? Excel難しい(´・ω・`)


        こんにちは、ふじかーです。

        またExcelネタなんですが・・・だれか詳しい方教えてください。


        自分もExcelを業務で日常的に使っており、
        先日の記事に書いたような便利カスタマイズもして、

        セル内の関数は調べればまぁ大体なんとかなるし、関数で出来ないことはVBAでまぁ大体なんとかなるし
        ある程度Excelくわしい方だと、自分では思っていました。

        周りで「あれ、これどうやるんだっけ?」みたいな声があると
        「え、なになに?」と聞きにいって解決してあげる側だと、自分では思っていました。

        あの日までは。


        問題発生


        ある日、集計表をつくる際に
        「列内で、値が入り始めたセルの 行番号 が知りたい」
        というケースがありました。




        ふむ。まぁパッとは思いつかないのですが

        だいたい同じような問題を抱えた先人たちが
        Yahoo知恵袋あたりで質問・解決しているもんです。

        お知恵を拝借して今後の糧とすべく、
        ググってみるとこれも全く同じのがありました。

        エクセルで各列における最初の空白以外の最初のセルの行番号を取得する方法 ...


        そこで出てきたベストアンサー

        ◆これでいかがでしょう
         =MATCH(0,INDEX(0/(B2:B12<>""),),0)


        おーすばらしい。試してみると確かに意図通り値が取れました。
        さすがベストアンサー、私も いいね しときました。



        が・・この式、何しているのか解ります?

         =MATCH(0,INDEX(0/(B2:B12<>""),),0)

        私にはピンときませんでした。
        気にせず使えば問題も解決しますが、今後の糧になりません(´・ω・`)


        分解

        良く判らないときは、バラして考えるもんです。
        とりあえず MATCH関数 と INDEX関数 が使われていますね。
        どっちも普段つかいません。それぞれの意味を確認しましょう。

        • MATCH関数
        指定範囲の中から、指定された検索値と一致するセルの 位置 を
        取得する関数だそうです。

        書式
        MATCH(検索値, 検索範囲, 照合の型:0=完全一致 )

        例


        ではベストアンサーのMATCH部分を見てみましょう。
         =MATCH(0, INDEX(0/(B2:B12<>""),), 0)
        の赤字部分。

        「INDEX関数の結果」が 検索範囲となって、
        その内から「0」の位置を探しているようです。ふむふむ。


        • INDEX関数
        指定範囲の中から、指定された行にある セルの参照 を
        取得する関数だそうです。

        書式
        INDEX( 対象範囲 ,  行番号 ,  列番号 )

        ・行番号:必須。対象範囲が 1行 のときのみ省略可。0 指定すると行全体を取得。
        ・列番号:必須。対象範囲が 1列 のときのみ省略可。0 指定すると行全体を取得。


        例


        ではベストアンサーのINDEX部分を見てみましょう。
         =MATCH(0, INDEX(0/(B2:B12<>""),), 0)
        の赤字部分。。。

        書式と並べてみると
           INDEX( 対象範囲           , 行番号 )
           INDEX( 0/(B2:B12<>"") ,           )

        あぁ、なるほどわからん。

        ・0/(B2:B12<>"") って何? これが対象範囲?
        ・行番号、指定されてませんけど?
        ・この INDEX関数 の結果が、MATCH関数に指定する「検索範囲」??

        多分、B列が「""かどうか」を true=1 or false=0 でみて
        0かErrかの配列としてMATCH式に突っ込んでるのかなーと思うんですが

        ググってすぐ出てくるようなExcel入門ページには
        こんなINDEX関数の使い方載ってませんし、思いつきません。

        うーん、奥深すぎ・・・orz

        2018年12月14日金曜日

        文字コード変換はコマンド一発で解決!



        こんにちは。よっしーです。

        今日は文字コードについてのお話しをしたいと思います。


        今まで、いろいろなプロジェクトに携わってきましたが、

        開発環境、実行環境などによって、ソースファイルの文字コードが決まっており、

        開発者が文字コードを「意識する」という場面がよくあります。


        使用するテキストエディタ、ツール等によるところがありますが、

        新規作成したソースファイルを保存する際、デフォルトの文字コードが決まっており、

        そのデフォルトの文字コードが、期待する文字コードになっていないと、

        知らず知らずのうちに、プロジェクトに沿わない文字コードで

        ソースファイルを生成してしまうこととなります。


        チームで開発をしていると、ソースファイルを集約したときに、

        ファイル毎に文字コードがばらばら。。。なんてことも、よくありますよね。


        で、そういったとき、ソースファイルの文字コードを正しいものに「変換」するのですが、

        Windows でいろいろと文字コード変換ツールを使ってはみたものの、

        あまりしっくりくるものがなく、いろいろと試した結果、Linuxコマンドを

        使用して変換する。というスタイルに落ち着きました。


        なので、今回は文字コード変換の方法についてご紹介したいと思います。

        (例のごとく、Ubuntu環境でのやり方となります)




        はじめに、nkf というコマンドを使用しますので、インストールします。

        nkf コマンドをインストール
        $ apt-get install nkf


        あとは、いろいろなコマンドとを組み合わせて使います。

        まずは、現在のファイルがどのような文字コードになっているかを確認してみましょう。


        複数ファイルの文字コードをコマンド一発で確認
        $ find . -type f | xargs nkf --guess | column -s: -t

        出力結果
        ↓ファイル名↓文字コード
        ./inc/client_recv.hUTF-8 (BOM) (LF)
        ./inc/client_send.hUTF-8 (BOM) (LF)
        ./inc/main.h       UTF-8 (BOM) (CRLF)
        ./inc/svc_recv.h   Shift_JIS (CRLF)
        ./inc/svc_send.h   Shift_JIS (CRLF)
        ./src/client_recv.cUTF-8 (LF)
        ./src/client_send.cUTF-8 (LF)
        ./src/main.c       UTF-8 (BOM) (CRLF)
        ./src/svc_recv.c   Shift_JIS (CRLF)
        ./src/svc_send.c   Shift_JIS (CRLF)

        ファイルによって文字コードや改行コードがバラバラですね。。。


        で、これを1つの文字コードに統一するため、変換をかけます。

        複数ファイルの文字コードをコマンド一発で変換

        ※ Shift-JIS、改行コード=CR+LF にする場合
        $ find . -type f | xargs nkf --overwrite -s -Lw

        ※ UTF-8、改行コード=LF にする場合
        $ find . -type f | xargs nkf --overwrite --oc=UTF-8 -Lu

        ※ UTF-8(BOM付)、改行コード=LF にする場合
        find . -type f | xargs nkf --overwrite --oc=UTF-8-BOM -Lu



        UTF-8、改行コード=LF の変換をかけた後、文字コード確認をしてみると、、、

        出力結果
        ./src/client_recv.cUTF-8 (LF)
        ./src/client_send.cUTF-8 (LF)
        ./src/main.c       UTF-8 (LF)
        ./src/svc_recv.c   UTF-8 (LF)
        ./src/svc_send.c   UTF-8 (LF)
        ./inc/client_recv.hUTF-8 (LF)
        ./inc/client_send.hUTF-8 (LF)
        ./inc/main.h       UTF-8 (LF)
        ./inc/svc_recv.h   UTF-8 (LF)
        ./inc/svc_send.h   UTF-8 (LF)
        キレイに文字コードがそろってますね!


        ファイルをテキストエディタで開いて、文字コードを指定し保存する。

        というやり方でもよいですが、ファイルの数が多くなってくると、

        かなり手間になってしまうので、そんな時はコマンド一発で一気にやってしまいましょう!


        ではまた~。

        2018年12月7日金曜日

        ExcelでF1を押してもヘルプが出ないように



        こんにちは、ふじかーです。

        先日「Excelがもっと捗る小技」をいくつか紹介しましたが
        ひとつ大事なのを忘れてました。


        誤って F1 を押したときに出るヘルプがうざい


        もっとも不要と思われるキー「F1」。

        大人気の主要キーである「F2」「ESC」の間に隠れて、自分も押下されるのを待ち続け
        ついブラインドタッチミスで押されようもんなら

        お前は必要ない

        と見たくもないのに最前面に姿を現し、しかも重くイラッとさせられる。
        そんな経験、誰しもあるんじゃないでしょうか。

        このF1ヘルプ、周りで使っている人見たことありません。
        私も活用したこと無いですし、あなたもおそらく無いでしょう。

        皆これには辟易としているようで、
        こいつを出なくする方法を検索するとたくさん出てきます。

         ①キーボードのF1キーを抜く
         ②F1ブレイカーというアプリを入れておく
         ③レジストリを書き換える
         ④マクロを利用する

        などなど。
        ①②③ はちょっと過激なので ④ をチョイスします。

        マクロでの対処方法をググってみると
        「個人用マクロブックを使う」という記事が多いようです。


        「個人用マクロブック」とは
        マクロの記録画面で選択できる保存先の一つなんですが

        これは、一度使うと「PERSONAL.XLSB」というブックが生成され、それ以降
        Excelの起動と同時に、こいつも背後でこっそりと自動的に開かれるようになります。

        一応これを使っても実現可能なんですが、
        これだとExcelを同時に複数、別ウィンドウで開いた時に

        と出るようになり、これはこれでイラッとするので却下。


        私は「アドインとしてマクロを組み込んでやる」方向で対応しました。


        対策方法


        対応の流れは
         1.ExcelファイルOpen時にF1を無効にするVBAマクロを書く
         2.マクロをアドインとして保存する
         3.アドインを有効化
        という感じ。


        1.ExcelファイルOpen時にF1を無効にするVBAマクロを書く
        ・Excelを新規に開き、
        ・Alt+F11を押下してVBEditorを開いて、
        ・ThisWorkbookをダブルクリックして開き
        ・下記のコードを貼り付ける

        Private Sub Workbook_Open()
        
            Application.OnKey "{F1}", ""
        
        End Sub
        
        ・VBEditorを閉じる



        2.マクロをアドインとして保存する
        ・「名前を付けて保存」画面を開き、
        ・ファイルの種類で「Excelアドイン(*.xlam)」を選択
        ・勝手にアドインフォルダが開かれるので
        ・適当に名前を付けて保存(ここでは 「F1ヘルプ無効化」 にします)





        3.アドインを有効化
        ・Excelを表示した状態で 「Alt」「T」「O」 と順番に押下し、Excelのオプション画面を開く
        ・アドイン → 設定(G) をクリック
        ・上で作成した F1ヘルプ無効化 にチェックをいれて、OKで閉じる
        ・Excelを一度閉じる






        以上、終了です。これでもう、あの大嫌いだったF1ヘルプは
        どれだけプッシュしようが出てこなくなりました。少し寂しいくらい。

        同じようなストレスを抱えてる方がいれば、参考にして下さいな。