2017年2月15日

[c/c++]テストの分割(fff)

書くネタが無いときは、だいたい実装作業ではなく、テストをやっているような気がする。。。

 

私はCで書いたライブラリのテストをするとき、fffを使うことが多い。
meekrosoft/fff: A testing micro framework for creating function test doubles

gtestも入っているので、ASSERT_EQ()なんかを書いてそれっぽく(?)できる。
使いこなしているわけではないが、スタブというかドライバというかモックというか、そういうのを準備する手間が楽になるだけでもありがたい。


今までうまくできていなかったのが、テストのソースファイルを分割する作業だ。
テストの関数は、比較的大きくなりがちなので、1ファイルに対してテストを1つのファイルにまとめると、かなり長くなってしまう。
元のソースこそ分割すべきなのか?と悩まないでもないが、せっかくのstatic変数をファイル分割するだけのために公開するのも避けたい。

私は、テスト対象のstatic変数も見たいと思うことがあるので、ソースファイルごとincludeさせている。
https://github.com/hirokuma/fff_examples/blob/master/test_func.cpp#L12
邪道といえば邪道だが、テストだからいいと思っている。
こうしていると、テストファイルを分割するとリンク時に多重定義が発生してしまう。

それに、モック関数もある。
ファイルを分割しても、モック関数として同じ名前のものはしばしば使うことになる。
そこにFAKEマクロを使ってそれぞれのテストファイルにモック関数を作ると、これはこれで多重定義になる。
(namespaceの中に入れてもダメだったけど、なんでだろう?)


そこでようやく思い至ったのが、テスト関数もincludeしてしまえばいいやん、ということだ。
そして、モック関数もincludeする。
見た目上だけテストファイルを分割するけど、実質は1つのソースファイルとしてコンパイルしてしまえ、ということだ。

格好は悪いが、テストだから、あまりそこに力を入れたくない。
懸念は、本体のソースファイルを変更してもテストでmakeしてビルドされないというところだったが、依存関係を書いてしまえばよい。
その編を解決しようとしていたのが、数日前の依存関係のパスの書き方についてだ。
http://hiro99ma.blogspot.com/2017/02/ccmakefiledepend.html

 

うちでは、gcc+fff+gtest+lcovという構成でテストをすることが多い。
lcovはHTMLでカバレッジを見るだけだが、目視できるところがよい。
「100%にしてやるぞー!」と思ってしまい、やらなくてもよいテストまでやってしまいがちなところが難点だが、まあこれは私の課題だな。

2017年2月14日

Azure無料試用版の最終日

ごめんなさい、今日はネタが思いつかなかったです。。。

ちょうどAzure無料試用版の最終日なので、証拠を残しておきます。

image

 

ちょこちょこと、Ubuntu VMを動かしたりしましたが、一人で家で使う分にはVirtualBoxなどの方が小回りがきいてよいかも。
Azureがどうとかではなく、私だと使い道がなかった、ということだ。

image

 

複数箇所からアクセスするなら、家にサーバを立てて公開して電源を入れっぱなしにするのとどっちがよいか、というところですかね。
古いPCを利用するならまだしも、新しいのを買ってきてサーバにするのであれば、悩むかもしれん。
だって、PCがずっと動いていると、そこそこ音がするし、夏は暑くなるし。

 

覚えていたら、明日・・・というか今日の23時過ぎからVMにログインしして、時間切れになったらどうなるかを見てみたいところ。
あー、忘れるだろうなぁ。


2017/02/14 22:14

忘れていなかったので、SSHでログイン・・・できませんでした。
既に、停止していました。

image

こうなるのねぇ。
日本時間の今日じゃなくて、実は朝の9時には停止していたのかもしれない。
まずはVMを削除してしまおう。

無料でも、制限はありますがこれだけ使えるそうです。
https://azure.microsoft.com/ja-jp/free/pricing-offers/

ネットでお仕事してないので、ピンとこんのです。。。

2017年2月11日

[c/c++]フリースタンディング環境

Cで書いていて、「これって、この環境で使える関数だっけ?」と考えないといけないことがときどきある。

たとえば、malloc()。
リンカで動的に使用するメモリを確保していなければ呼び出せても使えないし、malloc()自体を自分で定義しないといけないということもある。

そういう「標準じゃない」という環境を指す言葉があったのだけど、なんだっただろうか・・・。
オライリーの『Cクイックリファレンス』を読んでいて思いだした。
「フリースタンディング環境」だ。

 

本では、p.110などに説明がある。
詳細は本を読んでいただきたいが、「ホスト環境」は標準ライブラリがフルセットで使用でき、フリースタンディング環境は最小機能だけが使える、となっている。

最小機能ってなんだよ、ということになるのだが、p.276に使用できるヘッダが書かれている。
9つだ。
ただ、これも9つしか使えないわけではないし、この9つも必ずフル機能が使えるかといえば、そうでもないのだろう。
例えば、NordicのnRF51822みたいにOSが載っていない環境でgccを使っていたが、stdlib.hなんかを使った気がする。

 

一番わかりやすいのは、main()で始める必要がない、というところか。
混乱するし、他の名前を付ける理由もないからだいたいmain()にするとは思うが。

ただ、関数コールせずにジャンプで呼ばせることは多いかもしれん。
だって、main()を抜けて何か処理をさせたいわけでもないし、そもそも何か処理をしたいならmain()の最後に書いておいた方が自由度があるので、関数コールしてスタックを消費したくないのだ。

2017年2月10日

[c/c++]Makefileのdependは名前一致なのか

久々にMakefileを使って、ちゃんとビルドさせようとしている。
何度やっても慣れないMakefileだ。。。

 

Makefileに慣れていないので、ほどほどに応用が利きそうなMakefileのテンプレートを作っておき、それをコピーして使い回している。
automakeなんかもやろうとしたけど、うーん、よくわからんかったのだ。
今は、Nordicのプロジェクトに入っていたMakefileを改造して使っている。

私が見てきたMakefileでは、コンパイルする対象の書き方が2パターンあった。

  • オブジェクトファイル名(.o)を列挙して、コンパイル時に.c/.cppに変換
  • ソースファイル名(.c, .cpp)を列挙して、target指定用は.oに変換

この辺は、オブジェクトファイルの置き場所や、Makefileを分散して書くかどうかというのと関係しそうな感じはする。
私は、オブジェクトファイルは1箇所にまとめて、Makefileも1ファイルで済ませたい。
ただ、ソースファイルはディレクトリごとに分かれていたりするので、ディレクトリを含めてソースファイル名を書いている。
NordicのMakefileもそうなっていたので、私のよりも出来が良いから使わせてもらっている。

 

構成は、こういう風になっている。

  • OBJECT_DIRECTORY : オブジェクトファイル置き場
  • TARGET_SRC : ビルド対象のソースファイルたち
  • OBJECTS : オブジェクトファイル名たち

TARGET_SRCは自分で記入し、OBJECTSは変換して作るようになっている。

SRC_FILE_NAMES = $(notdir $(TARGET_SRC))
OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(SRC_FILE_NAMES:.cpp=.o) )

もちろん、ビルドなんかは普通に動作する。


で、ここからが本題だ。

参考にしたMakefileは、依存関係を自動生成するようになっていなかった。
だから、ヘッダファイルを変更してもビルドしてくれず、cleanしてmakeしなおしていた。

こういうときは、makedependか、-MMとかだったな、と思って過去Makefileを探したところ、こういうのが見つかった。

.Depend:
    $(CXX) $(CXXFLAGS) -MM $(SRCS) > .Depend

include .Depend

ああこれこれ、と名前だけ変更して追加したのだが、動作が変わらない。
.Dependファイルを見ると、依存するファイル名の方はソースファイルやヘッダファイルにパス名が入っているものの、最初に各オブジェクト名(依存されている方だから、被依存?)の方はオブジェクト名が載っているだけで、OBJECT_DIRECTORYの場所になっていないのだ。

探すと、出てきた。
GCC makefile dependency generation path - Stack Overflow
-MTに続けてパス付きでオブジェクトファイル名を書いておけば、それがそのまま載ってくるようだ。
書き方の例もあったので、foreachするやつを作った。

 

が、全然効かない。
.Dependファイルは、ちゃんとパス付きでオブジェクトファイル名が載っているし、lsで見てもオブジェクトファイルは存在する。
なぜだ。。

もう一度.Dependを見てみると、オブジェクトファイル名は「obj/./test.o」のように、1つカレントディレクトリが挟まっていた。
これは、ソースファイルが「$(XX)/test.c」のように、ディレクトリ名が変数になっていて、それがカレントディレクトリなので「XX=.」としたからだった。

試しに外して「obj/test.o」の形式に書き直すと、効いた。
そうか、そういうしくみだったのか。
今回はBash on Windowsなので、その影響もあるかもしれんが、気をつけておこう。

2017年2月9日

[c/c++]0を代入したグローバル変数は初期値ありと見なされないようだ

以前から気になっていた、Cのグローバル変数を0で初期化したときの扱いだ。

01: #include 
02: 
03: static int a;
04: 
05: int main(int argc, char *argv[])
06: {
07:     printf("a=%d\n", a);
08: }

こう書いても、

01: #include 
02: 
03: static int a = 0;
04: 
05: int main(int argc, char *argv[])
06: {
07:     printf("a=%d\n", a);
08: }

こう書いても、普通のCコンパイラならaはmainが始まる前に0で初期化されるようにビルドする。
「普通は」と書いたのは、組み込み環境で、ものすごくメモリが少なかったら、そういうmainが始まる前の処理を呼ばないようにしてしまうという選択ができなくもないからだ。
コンパイラがやると言うよりも、実装した人がいじくることが多いだろうから、そういう環境は省略だ。

 

ただ、今回の話は、そのmainが始まる前の部分になる。
プログラムを実行すると、C言語ではmainから始まると表現しているが、グローバル変数なんかはmainに呼ばれる前に初期化されるので、当然mainより前が存在する。

その、main前の処理(C Runtimeとか呼ぶのか?)の中であれこれやっていたのだが、グローバル変数の初期化も行われていた。
やるのは、

  • 初期値無しグローバル変数を0でクリア
  • 初期値あり変数に初期値代入

だ。
その実装がどうなっていたか覚えていないが、memset()みたいなアセンブラ処理と、memcpy()みたいなアセンブラ処理があったような気がする(まだC89やANSI Cより前のコンパイラだった。。。)。


さて、昔話はここまでにして、気になっているのが何かを説明する。

上に2つソースを載せたが、どちらもaは0になる。
なるのだが、上は初期値無しなのだが、下は初期値あり(0)とみなすのか、0になるのがわかっているから初期値無し扱いなのか、だ。
初期値あり扱いになると、初期値をROMに持っておいて、それを初期値あり領域にコピーするような作りになってしまうので、できれば0初期値の場合は初期値を持っていないという扱いにしてくれるとうれしい。

じゃあ、最初から初期値を書かなければよいではないか、となるのだけど、初期値がある変数をずらずら書いているのに、0のところだけ何も書かないと、すっきりしないのだ。
そう、気分の問題である。
ソースファイルって、リズミカルに書くようにして、リズムが悪いところにバグがあるかも、というチェックができたらうれしいじゃないか。

 

■初期値無し
$ gcc -o tst -O0 -Xlinker -Map=map.map test.c
$ size tst
   text    data     bss     dec     hex filename
   1226     560       8    1794     702 tst

■初期値0
$ gcc -o tst -O0 -Xlinker -Map=map.map test.c
$ size tst
   text    data     bss     dec     hex filename
   1226     560       8    1794     702 tst

よかった、同じようだ。

試しに、初期値として3を代入させた。

text    data     bss     dec     hex filename
1226     564       4    1794     702 tst

sizeコマンドでは以下が出力される。

    • text : コード
    • data : 初期値あり変数
    • bss : 初期値無し変数

初期値があると、ちゃんと初期値あり変数の方に4byteが移動している。
じゃあ、初期値自体はどこにあるのかというと、textのはずだ。
textに変化が見られないのは、alignmentの波に取り込まれてしまったからだろうか。。。

 

ただ、これはグローバル変数にべたっと書いた場合で、構造体の場合はまた事情が違うだろう。
構造体の中のメモリが、初期値ありとなしで別になっていたら困るからね。。。

2017年2月7日

[c/c++]未だに「配列のポインタ」「ポインタの配列」に怯える

愚痴だ。
こう何十年もC/C++を使っているにもかかわらず、「配列のポインタ」「ポインタの配列」が、どっちがどっちかわからなくなる。
ネットで説明が出てくるので、困ったときには調べれば良いのだが、どうも身になっていない。

 

ポインタの配列は使うことが多いと思う。
文字列の配列なんかは、ポインタの配列扱いしてよいだろう。

const char *STRINGS[] = {
  "Hello", "my", "name", "is", "Taro", "Hara"
};

あまり意識したことがないのだが、この「*」は、const charの方にひっついているはずだ。

for (int lp = 0; lp < sizeof(STRINGS) / sizeof(STRINGS[0]); lp++) {
    printf("%s\n", STRINGS[lp]);
}

これで全部の文字列が出力されたので、まあよかろう。

 

優先順位が心配だから括弧で強制してしまえ!、という技が、型については使えないのが残念だ。
これができれば、優先順位を覚えていなくてもよいのだが。。。コンパイルエラーだ。

(const char *)STRINGS[] = {
  "Hello", "my", "name", "is", "Taro", "Hara"
};

だから、逆に考えて、括弧を付けてコンパイルエラーになる方が優先順位が高い、と覚えれば良いのか。
つまり、「ポインタの配列」の方が優先順位が高いことになる。

 

ポインタの配列を関数の引数にしたいことがあるけど、ダブルポインタにキャストして渡している。
他に方法が思いつかないのよねぇ。


では、括弧を付けられる方を見ていこう。
こっちが「配列のポインタ」のはずだ。

const char (*STRINGS)[];

でも、配列って、そもそもポインタと同じ扱いなんじゃないのか?
なんでわざわざ「配列のポインタ」なんてことにしないといかんのだろう。

const char a1[] = "Hello";
const char (*STRINGS)[] = &a1;
printf("%s\n", *STRINGS);

一応、これで動く。
例として意味は無いので、何か有効な使い道を思いつけば良いのだが、使い道が思いつかないから普段使わないのだ。

 

でも、&a1って、a1と同じ値だよね?

printf(" a1 = %p\n", a1);
printf("&a1 = %p\n", &a1);
a1 = 0x7fffe8c5b100
&a1 = 0x7fffe8c5b100

まあ、配列はアドレスに展開されるから、それに&をつけても同じアドレスになりますわな。
だからといって、代入するときに&を取り外すとコンパイルエラーになる。
数字の問題じゃなくて、文法の問題だからだ。
レジスタのアドレス値が分かっていたとしても、ポインタとしてキャストして代入しないとエラーになるのと同じだ。


これは、なんだろう?

const char (*STRINGS[]);

gccだと「invalid initializer」になるので、文法エラーじゃなくて、初期化子の書き方が間違っている、といっているような気がするのだが。。。

const char (*STRINGS[]) = {
    "Hello", "my", "name", "is", "Taro", "Hara"
};

ちっ、そんだけかい。

[c/c++]メモリのフラグメンテーションを減らしたい

久々に、Cで実装している。

今回、アプリから受け取ったデータをプロトコルに変換するようなライブラリを作っている。
アプリのデータサイズは想定できないし、プロトコル長の最大も決めづらい。
また、いくつプロトコルデータをアプリが持ちたいかも決められない。

となると、ヒープを使うしか無かろう。
malloc/freeだ。
あー、苦手なのよねぇ。。。

C++だとデストラクタでメモリ解放する、ということもできそうだが、Cだと思いつかない。
メモリの管理だけのためにまたメモリの使用量を増やすというのは、やりたくない。


まあ、そういうのは私が解決せんといかんことだろうが、別の点で気になることがある。
メモリのフラグメンテーションだ。

10年前、いや、もう少し前になるだろうか。
今よりも多少冴えていて、体力もあった私は、C++で組み込みアプリを実装していた。
画像データを扱ったり、画像をファイルに変換したりしていたので、new/deleteしていた。
デストラクタでメモリ解放漏れのチェックなんかもして、そういう方面は問題なかろうと思っていた。

が、だ。
テストのため、帰る前に自動で処理するようにしておき、翌日見に行くと、どうも処理が遅いような気がする。
気のせいかと思って、土日に連続運転させて月曜日出社すると、1秒もかからずに終わっていた処理が、分単位でスローモーションのように動いていたのだった。。。

メモリの解放漏れなどないのに!?と思ってあちこちの人に聞いたところ、メモリのフラグメンテーションではないか、という意見があった。
試しに、画像処理のメモリを毎回new/deleteしていたところを、最初にnewしたまま使い回すように変更したら、発生しなくなった。

いやぁ、そこそこ組み込みの世界を理解してきたと思い込んでいただけに、衝撃でしたわ。
Linuxだと、メモリが分断されても、うまいことOSがつながった大きい領域に見せかけて使うことはできるのだけど、あくまでソフトウェアとしてつながって見えるだけで、分断された部分を使う処理の負荷が大きくなったとか、そんなことだったと思う。
Linux 2.18とか、そのくらいだったと思うので、今はまた事情が違うかも。

 

それ以来、ヒープメモリの確保と解放に怯えるようになりましたとさ。
めでたしめでたし。


Boostには、メモリプールというやつがあって、そういうフラグメンテーションが置きにくいようにできる、というのを読んだ気がする。
やったことないので、リンクだけ載せておこう。

Chapter 4. Boost.Pool

2017年2月5日

[c/c++]mallocと代入の狭間で

可変長のバッファを作ろうとした。
Cなので、バッファ長も一緒に管理したいので、ありがちな構造体にした。

struct {
  uint8_t   len;
  uint8_t   *buf;
};

まあ、先頭アドレスとサイズがわかればよいので、こうすることが多いだろう。

 

さっきまで、malloc()して可変のバッファを作っていたのだが、ときどきソースコードに埋め込むバッファも使うことがあった。

const uint8_t DATA[] = {
  0xaa, 0xbb, ....
};

値を変更する予定がないので、constを付ける。
付けなかったら、初期値ありのRAMデータになるので、ROMにもRAMにもメモリがいるようになるので、constは付けておきたいところ。

 

が、constポインタのものを非constポインタに代入するというのは、やはりよろしくない。
では、これをwarningするのをキャストで回避すべきか?
そこは悩ましいところだ。
今は自分で分かって実装しているから良いものの、何か事情が変わってしまうと、安全では無くなるかもしれない。

じゃあ放置するか?
そうすると、warningがうっとうしい。
警告はしてほしいけど、今は私が分かっているから警告してほしくない、という、コンパイラには理解できない状況だ。
もし、コンパイラがスルーすると、タイミングによっては「なんで警告しないんだ!」と私が怒るかもしれない。

 

では、構造体の方をconstポインタにすれば良いかというと、そういうわけでもない。
今度はfree()の方で警告されてしまう。
free()自体はポインタ先を書き換えることはないのだろうが、free()するのはmalloc()したところであり、malloc()はconstポインタを返さないので、free()の引数がconstポインタなのはおかしい、ということか。
まあ、メモリを解放してほしいのに、constもなにもあったもんじゃなかろう。


まだ、これについて私の中で解決ができていない。
標準関数を優先して、自分では書き換えないように意識し、constポインタを非constポインタに置き換えて使う、というところか。

回避しているだけよねぇ。。。
でも、私が使う場合にはコンパイルレベルで解決してほしいところなので、こうなってしまいそうに思う。
RAMに空きがあっても、crtなどで初期値をRAMに転送する、などと思ってしまうと、実装の危険があったとしてもキャストしてしまいそうだ。
だって、ROMに書込もうとしたら、OSがあっても無くても、だいたい教えてくれるだろう?

typedef struct {
  uint8_t len;
  uint8_t *buf;
} buf_t;

const uint8_t DATA[] = { 0, 1, 2 };
const buf_t buf = { sizeof(DATA), (uint8_t *)DATA };
buf.buf[0] = 5;

Linuxだと、このくらいは動いてしまうし、Segmentation Faultなどが発生しないのだ。
まあ、文句は言えないのだけど、定数値がコード領域に置かれて、コード領域へのメモリ書込みで例外が発生するのだったら、実行時に例外が発生するかと思ったのだ。


構造体の構成は同じで、ポインタにだけconstをつけた。

struct {
    uint8_t len;
    const uint8_t *buf;
};

そして、値を変更しない関数はそっちを引数に取るようにした。
constが付いていないデータを使いたいなら、こっちの構造体でキャストして使う。
キャストで回避するしかないのだが、constが付く方にキャストするのだったら、まだよいのではなかろうか。

 

だいたい、メンバにポインタを含んだ構造体にconstを付けても、そのメンバがconstになるわけではないから、もうこういう手段しかないような気がする。
しかし、構造体のメンバが構造体で、そっちにもポインタがあったらどんどんと連鎖していってしまう。。。

かといって、自動的にconstが内部メンバに波及してしまうという言語仕様になってしまうと、それはそれで自由度がなくなる。
案外、gcc拡張とかで「波及的const」なんてものがあるのかもしれん。ないか。

__attribute__(const)とか__attribute__(pure)で変更しないことを表せるかと思ったが、関数内で引数の構造体メンバが指している先を書き換えてもエラーにならないし、実行しても動いた。
単に最適化だけの話か。
結局、運用でカバーしよう、で終わってしまいそうな気がする。

2017年2月4日

[bow]valgrindがBash on Windowsでうまく動かない

久々にCで作っているのだが、malloc()なんかを使うので、メモリリークが心配。。。
そんなときは、valgrindだ!

という知識はあるものの、使ったことは無かった。
せっかくなので、Bash on Windowsで動かそうとapt installした。
・・・動かない?

Bash on Windows (Windows Subsystem for Linux) でvalgrindを動かす - wagavulin's blog

ああ、そうなんですか。
ソースからビルドすると、確かに動いた。


というところまでよかったのだが、今度は動作自体がおかしい。
valgrindなしで動かすと正常に動くのだが、valgrindで動かすとSegmentation Faultが発生する。
どうも、valgrind自体が落ちているような感じがする。
「General Protection Fault」などとも出てくる。

Running valgrind throws General Protection Fault on dl-misc.c · Issue #1295 · Microsoft/BashOnWindows

これかな?
まだopenだから、直ってないということか。

試しに、同じソースを普通のUbuntu16.04でvalgrindしたら、ちゃんと動いてくれた。
ふっ、Bash on Windowsもまだまだじゃのぅ。

2017年2月2日

[n5]Nexus5から搬送波が出なくなった→復活!

開発関係の話じゃ無くて済まないが、私にとっては緊急事態に等しい。
Nexus5から搬送波が出なくなったのだ。

数日前から発生している。
まったく出ないわけでは無く、弱々しく出るときもあれば、出なくなるときもある。
タグの読込はできないし、SNEPもしない。
うーむ。。。

もう、フルバックアップして、端末リセットするしか無いか。。。
Nexus7もがんばってはくれているのだが、やはりこのサイズでNFCが載っているのはありがたいのだ。
もしリセットで復旧しなかったら、買い直すことになるのだろうか。

 

しかし、nRF52でType4に対応したというのに、何というタイミングか・・・。
New NFC feature on nRF52 series: Read/write capable Type 4 Tag NFC library in nRF5 SDK


2017/02/03

Androidの設定画面から端末リセットを行ったが、復帰せず。。。
搬送波の出方が、相変わらず微妙で、位置がいつもの背面のところよりもかなり下の方でしか確認できない。
落下したことで、なんか部品がずれたりしてるとか?
まさかなぁ。

 

せっかくだから、ファクトリーイメージを焼くところまでやっておこう。
https://developers.google.com/android/images

焼けない?

FAILED (command write failed (No error))

やり方を間違ったのかと思ったが、手順はそんなに変わらんし。
・・・USBハブ経由で挿していたのだが、PCに直接挿すとflash-all.batが動いた。
なんだったんだ。。。

そして、焼き直したけど・・・ダメ。
そうよねぇ、ダメよねぇ。

 

ちょうど今日は日本では節分という行事がある日なので、そういうものにでもすがりつきたい心境だが、買い換えを検討するのが妥当だろうな。


毒くらわば皿まで、という言葉が日本にはあります。
あきらめろ?
中途半端で終わらせるな?
そんな意味合いなのでしょうか。

ここまでやったので、裏蓋を開けてみました。

image

爪で開けようとして失敗したので、ビックカメラのカード(10年くらい前に作ったやつなので、今は違うかも)が薄かったので、それを電源ボタン辺りに差し込んで、ぐいっとひねったところ、ようやく1箇所だけ開いた。
あとは、Tポイントカード(これも10年くらい前)が厚めだったので、使い分けながらやっていくと、なんとか開いた。

左側の黒いやつが、NFCアンテナなのかな?
ということは、その上にある4つの接点で本体と接しているのか。

アンテナの右上にある丸いのは、ボタン電池かと思ったが、たぶんセンサだろう。
なんだろう、磁気とかか?

蓋を外した状態で立ち上げ、搬送波を確認したがまったく出ていなかった。
やはり、蓋の裏にあるやつがNFCアンテナか。
運が良ければ、この接点の接触が悪いために出ていない、というだけかもしれん。
アルコールで拭いて、カッターの先っちょで本体側の接点をもう少し持ち上げて、蓋を閉じる。

そして端末を起動すると・・・搬送波復活!
タグも読めるし、SNEPもする!
よかった。。。。


そのあと、しばらくすると、また読めなくなった。
が、接点の辺りを蓋の上から押すと、読めた。

うちの場合は、黄色の丸で囲んだところ辺りに、NFCアンテナの接点があった。
ここが離れているとき、指で軽く押すと、カチッと接触するような音が聞こえた。

image

押すといっても、力を入れるか入れないか、という程度のものだ。
カチッという音も、ちょうど音が鳴るような距離が開いていたから聞こえたのだろう。
だから、押すとちょうど接触して読めたのだろう。

そういう状態であれば、蓋の外から押さえつけるか、蓋を変形してしまえば接触すると思う。
今回は、遠くからライターの火で炙って、少し温めてから少し曲げてみた。
今のところ、それで接触するようになったけど、湾曲しやすいところに接点を持ってくるというのは、あまりよくなかったんじゃなかろうか。
せめて、もう少し縁の方になっていれば、そういう影響はなかったんじゃなかろうか。
実際、NFC以外のアンテナは、縁の方に接点があったし。