ExcelのCSVデータ取り込みで「このテキストファイルのデータは、1つのワークシートに入りきりません。」というエラーになる場合の対処

March 27,2017 12:03 AM
Category:[Excel]
Tag:[Excel, Office]
Permalink

ExcelのCSVデータ取り込みで「このテキストファイルのデータは、1つのワークシートに入りきりません。」というエラーになる場合の対処方法を紹介します。

「このテキストファイルのデータは、1つのワークシートに入りきりません。」

1.問題点

ExcelのCSVデータ取り込みで「このテキストファイルのデータは、1つのワークシートに入りきりません。」というエラーが発生しました。

データは下記に示す、5行程度の短いものです。

テスト1-1,テスト1-2,テスト1-3
テスト2-1,テスト2-2,テスト2-3
テスト3-1,テスト3-2,テスト3-3
テスト4-1,テスト4-2,テスト4-3
テスト5-1,テスト5-2,テスト5-3

CSVファイルの取り込み手順は下記のとおりです。

「データ」→「外部データの取り込み」→「テキストファイル」をクリックしてインポートしたいCSVファイルを選択。

テキストファイル

「テキストファイルウィザード - 1/3」画面にある、「元のファイル」から「65001 : Unicode (UTF-8)」を選択。

(クリックで拡大)
65001 : Unicode (UTF-8)

プレビューで正常に表示されていることを確認して「次へ」をクリック。

プレビュー

「カンマ」をチェックして「完了」をクリック。

開始セル(ここではA1)を指定して「OK」をクリック。

開始セル(ここではA1)を指定

ここでタイトルの「このテキストファイルのデータは、1つのワークシートに入りきりません。」というエラーに遭遇します。

(クリックで拡大)
「このテキストファイルのデータは、1つのワークシートに入りきりません。」

ちなみにこのダイアログを「OK」をクリックしてとじると、次のように最初の1行だけが取り込まれた状態になります。

最初の1行だけが取り込まれた状態

1つのワークシートに入りきらない量ではないので、対処方法が分かりません。

ということで、「このテキストファイルのデータは、1つのワークシートに入りきりません。」というエラーになる場合の対処方法を紹介します。

2.原因

このメッセージが表示される原因は、CSVファイルの改行コードがLFになっている場合に発生するようです。

エラーメッセージのあとに最初の1行しか取り込めていないのは、1行目の改行コード以降が正常に読み込めないためと思われます。

3.対処

テキストエディタでCSVファイルを開き、改行コードをCRLFに変換して保存します。

これで正常に取り込むことができます。

正常に取り込む

Comments [0] | Trackbacks [0]

ExcelでUTF-8のCSVデータを取り込む方法

March 24,2017 12:03 AM
Category:[Excel]
Tag:[Excel, Office]
Permalink

ExcelでUTF-8のCSVデータを取り込む方法を紹介します。

1.問題点

次のような文字コードがUTF-8のCSVファイルがあります。

テスト1-1,テスト1-2,テスト1-3
テスト2-1,テスト2-2,テスト2-3
テスト3-1,テスト3-2,テスト3-3
テスト4-1,テスト4-2,テスト4-3
テスト5-1,テスト5-2,テスト5-3

このファイルをダブルクリックしてExcelに取り込むと、文字化けします。

こういう場合、テキストエディタでCSVファイルを開き、文字コードをShift_JISに変換して一旦保存し直してから取り込むのですが、編集後もUTF-8のまま保存したいので、できればそのままの文字コードで開きたいです。

ということで、ExcelでUTF-8のCSVデータを取り込む方法を紹介します。

2.UTF-8のCSVデータを取り込む

UTF-8のCSVデータを取り込むには、「データ」→「外部データの取り込み」→「テキストファイル」をクリックしてインポートしたいCSVファイルを選択。

テキストファイル

「テキストファイルウィザード - 1/3」画面にある、「元のファイル」から「65001 : Unicode (UTF-8)」を選択。

(クリックで拡大、以下同様)
65001 : Unicode (UTF-8)

プレビューで正常に表示されていることを確認して「次へ」をクリック。

プレビュー

カンマ区切りなので「カンマ」をチェックして「完了」をクリック。

カンマ

開始セル(ここではA1)を指定して「OK」をクリック。

開始セル(ここではA1)を指定

これでCSVデータが正常に読み込まれます。

CSVデータ

3.BOMつきのUTF-8にする

BOMつきのUTF-8であれば、ダブルクリックでそのまま開けます。

BOMというのは、ファイルの先頭につけられたバイトオーダーマーク (byte order mark) のことで、UTF-8の場合「0xEF 0xBB 0xBF」という文字が付与されます。

ダブルクリックでExcelを開いたとき、ExcelはファイルのBOMをチェックして、「BOMがあればUTF-8」で開くという動作になっているようです。

UTF-8ファイルにBOMを付与するには、Windowsのメモ帳でCSVファイルで開き、そのまま保存すればOKです。

4.その他

UTF-8にはBOMあり・BOMなしの2種類がありますが、確認したところどちらのデータも正常に取り込めるようです。

ただし改行コードはCRLFになっている必要があります。

Comments [0] | Trackbacks [0]

IEで「前回のブラウズ セッションは予期せずに終了しました「セッションの復元」」が表示される場合の対処

March 23,2017 12:03 AM
Category:[IE]
Tag:[IE]
Permalink

IEで「前回のブラウズ セッションは予期せずに終了しました「セッションの復元」」が表示される場合の対処方法を紹介します。

1.問題点

IEを起動するたびに「前回のブラウズ セッションは予期せずに終了しました「セッションの復元」」が表示されます。

(クリックで拡大)
前回のブラウズ セッションは予期せずに終了しました「セッションの復元」

が、「セッションの復元」をクリックしても前回のセッションが復元されません。

復元はされなくてもいいのですが、このメッセージが表示されないようにする方法が分かりません。

ということで、IEで「前回のブラウズ セッションは予期せずに終了しました「セッションの復元」」が表示される場合の対処方法を紹介します。

2.メッセージが表示されないようにする

メッセージが表示されないようにするには、「ツール」アイコン→「インターネットオプション」をクリック。

「詳細設定」タブをクリック。

「自動クラッシュ回復機能を有効にする」のチェックを外して「OK」をクリック。

これで「セッションの復元」のメッセージが表示されないようになります。

Comments [0] | Trackbacks [0]

Linuxで「Too many open files」というエラーになる場合の対処

March 16,2017 12:03 AM
Category:[Linux]
Tag:[Linux]
Permalink

Linuxで「Too many open files」というエラーになる場合の対処について紹介します。

ここではnkfコマンドを例にしていますが、他のコマンドでも適用可能です。

1.問題点

nkfで1000ファイルほどの文字コードをUTF-8に変更しようとしたところ、「Too many open files」というエラーに遭遇しました。

% nkf -w --overwrite *
hoge.txt.nkftmp6vpeDo: Too many open files

エラーの後、該当ファイル以降の文字コードが変換されていませんでした。

2.原因

エラーになる原因は、nkfコマンド実行時、プロセスが開けるファイルディスクリプタの上限数を超えてしまうためのようです。

3.対処

nkfではファイルディスクリプタの上限数を設定できないため、findコマンド、xargsコマンドと組み合わせて実行します。

% find . -type f | xargs -n 256 nkf -w --overwrite

xargsの-nオプションで、nkfコマンドに一度に渡す引数の数を制御できます。

ここでは256を設定していますが、256を超えたら繰り返されます。

Comments [0] | Trackbacks [0]

C/C++でSegmentation faultが発生した場所を特定する方法

March 14,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C/C++でSegmentation faultが発生した場所を特定する方法を紹介します。

1.問題点

下記のサンプルプログラム(test.cc)を作りました。

test.cc

#include <stdio.h>
 
void test() {
    char *p;
    p = 0;
    printf("%c\n", *p);
}
 
int main() {
    test();
    return 1;
}

コンパイルします。

% g++ -g test.cc

このプログラムを実行するとSegmentation faultが発生します。

% ./a.out
Segmentation fault (コアダンプ)

が、どこでエラーが発生しているのかわかりません。

ということで、C/C++でSegmentation faultが発生した場所を特定する方法を紹介します。

使用しているLinuxはCentOSです。

本来解としてコアダンプを解析する方法もありますが、そちらについては別途エントリーします。

2.Segmentation faultが発生した場所を特定する

Segmentation faultが発生した場所を特定するには、下記の環境変数を設定します。

% export LD_PRELOAD="/lib64/libSegFault.so"
% export SEGFAULT_SIGNALS="all"

上記は64bit版で、32bit版の場合は下記です。

% export LD_PRELOAD="/lib/libSegFault.so"
% export SEGFAULT_SIGNALS="all"

これでサンプルを実行すると、エラーの詳細が出力されます。

% ./a.out
*** Segmentation fault
Register dump:
 
 RAX: 0000000000000000   RBX: 0000000000000000   RCX: 0000000000400570
 RDX: 00007ffeeac84158   RSI: 00007ffeeac84148   RDI: 0000000000000001
 RBP: 00007ffeeac84050   R8 : 00007f197757ae80   R9 : 0000000000000000
 R10: 00007ffeeac83eb0   R11: 00007f19771e0a20   R12: 0000000000400440
 R13: 00007ffeeac84140   R14: 0000000000000000   R15: 0000000000000000
 RSP: 00007ffeeac84040
 
 RIP: 0000000000400544   EFLAGS: 00010202
 
 CS: 0033   FS: 0000   GS: 0000
 
 Trap: 0000000e   Error: 00000004   OldMask: 00000000   CR2: 00000000
 
 FPUCW: 0000037f   FPUSW: 00000000   TAG: 00000000
 RIP: 00000000   RDP: 00000000
 
 ST(0) 0000 0000000000000000   ST(1) 0000 0000000000000000
 ST(2) 0000 0000000000000000   ST(3) 0000 0000000000000000
 ST(4) 0000 0000000000000000   ST(5) 0000 0000000000000000
 ST(6) 0000 0000000000000000   ST(7) 0000 0000000000000000
 mxcsr: 1f80
 XMM0:  00000000000000000000000000000000 XMM1:  00000000000000000000000000000000
 XMM2:  00000000000000000000000000000000 XMM3:  00000000000000000000000000000000
 XMM4:  00000000000000000000000000000000 XMM5:  00000000000000000000000000000000
 XMM6:  00000000000000000000000000000000 XMM7:  00000000000000000000000000000000
 XMM8:  00000000000000000000000000000000 XMM9:  00000000000000000000000000000000
 XMM10: 00000000000000000000000000000000 XMM11: 00000000000000000000000000000000
 XMM12: 00000000000000000000000000000000 XMM13: 00000000000000000000000000000000
 XMM14: 00000000000000000000000000000000 XMM15: 00000000000000000000000000000000
 
Backtrace:
./a.out[0x400544]
./a.out[0x400566]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f19771e0b15]
./a.out[0x400469]
 
Memory map:
 
00400000-00401000 r-xp 00000000 fd:02 139776506                          /home/foo/a.out
00600000-00601000 r--p 00000000 fd:02 139776506                          /home/foo/a.out
00601000-00602000 rw-p 00001000 fd:02 139776506                          /home/foo/a.out
00894000-008b5000 rw-p 00000000 00:00 0                                  [heap]
7f1976fa9000-7f1976fbe000 r-xp 00000000 fd:00 201326729                  /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f1976fbe000-7f19771bd000 ---p 00015000 fd:00 201326729                  /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f19771bd000-7f19771be000 r--p 00014000 fd:00 201326729                  /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f19771be000-7f19771bf000 rw-p 00015000 fd:00 201326729                  /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f19771bf000-7f1977375000 r-xp 00000000 fd:00 201329562                  /usr/lib64/libc-2.17.so
7f1977375000-7f1977575000 ---p 001b6000 fd:00 201329562                  /usr/lib64/libc-2.17.so
7f1977575000-7f1977579000 r--p 001b6000 fd:00 201329562                  /usr/lib64/libc-2.17.so
7f1977579000-7f197757b000 rw-p 001ba000 fd:00 201329562                  /usr/lib64/libc-2.17.so
7f197757b000-7f1977580000 rw-p 00000000 00:00 0
7f1977580000-7f1977584000 r-xp 00000000 fd:00 201329559                  /usr/lib64/libSegFault.so
7f1977584000-7f1977783000 ---p 00004000 fd:00 201329559                  /usr/lib64/libSegFault.so
7f1977783000-7f1977784000 r--p 00003000 fd:00 201329559                  /usr/lib64/libSegFault.so
7f1977784000-7f1977785000 rw-p 00004000 fd:00 201329559                  /usr/lib64/libSegFault.so
7f1977785000-7f19777a6000 r-xp 00000000 fd:00 201329555                  /usr/lib64/ld-2.17.so
7f197798e000-7f1977991000 rw-p 00000000 00:00 0
7f19779a5000-7f19779a6000 rw-p 00000000 00:00 0
7f19779a6000-7f19779a7000 r--p 00021000 fd:00 201329555                  /usr/lib64/ld-2.17.so
7f19779a7000-7f19779a8000 rw-p 00022000 fd:00 201329555                  /usr/lib64/ld-2.17.so
7f19779a8000-7f19779a9000 rw-p 00000000 00:00 0
7ffeeac64000-7ffeeac85000 rw-p 00000000 00:00 0                          [stack]
7ffeeacdd000-7ffeeacdf000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Segmentation fault (コアダンプ)

最後に、「Backtrace:」の最初に表示されたアドレスをaddr2lineコマンドで変換すると、エラーになったファイルと行番号が表示されます。

% addr2line -e a.out 0x400544
/home/foo/test.cc:6

なお、この情報を出力するには、g++でビルドする際に"-g"オプションが必要です。

簡単なサンプルでしか確認していないので、すべてのパターンに適用できるか分かりませんがとりあえず。

Comments [0] | Trackbacks [0]

IEのタブに色がつく理由

March 9,2017 12:03 AM
Category:[IE]
Tag:[IE, Windows]
Permalink

IEのタブに色がつく理由を調べてみました。

1.はじめに

IEで複数のタブを開くと、下のスクリーンショットのように色がつく場合があります。

複数のタブ

逆に色がつかない場合もありますが、その違いがわかりません。

ということで、IEのタブに色がつく理由を調べてみました。

2.タブに色がつく理由

タブに色がつくのは、あるページから新しいタブを開いたとき、色分けすることでタブのグループをわかりやすくするための仕組みです。

たとえばYahooのページのタブをひとつだけ開いているときは色がつきません。

タブをひとつだけ開いているとき

この状態でページ内の任意のリンクを新しいタブで開くと、タブに色がつきます。

新しいタブ

Yahooとは関係のない別のページを開い、そのページにある任意のリンクを新しいタブで開くと、異なる色がつきます。

新しいタブ

配色の順序はランダムのようです。

3.色分けをやめる

色分けをやめたいときは、「ツール」→「インターネットオプション」をクリック。

インターネットオプション

「全般」タブ→「タブ」をクリック。

タブ

「タブグループを有効にする」のチェックを外して「OK」をクリック。

タブグループを有効にする

IE再起動後、色分けがされなくなります。

再起動後

4.色分けされた状態でタブを移動した場合

色分けされた状態のタブを移動した場合、移動したタブの色は、

  • 移動先の左右のタブの色が同じ場合、その色に変わる
  • 移動先の左右のタブの色が異なる場合、解除

となるようです(個人的にはこの仕様はどうかと思いますが...)。

移動元のタブ色も最後の1つになると色が解除されます。

移動前
移動前

移動後
移動後

Comments [0] | Trackbacks [0]

C++で「invalid abstract type~」というエラーになる場合の対処

March 8,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C++で「invalid abstract type~」「because the following virtual functions are pure within~」というエラーになる場合の対処方法について紹介します。

1.問題点

下記のサンプルプログラムを作りました。

sample.h

class Sample {
    public:
        Sample();
        void test1();
        virtual void test2() = 0;
};

sample.cc

#include <stdio.h>
#include "sample.h"
 
Sample::Sample() {
}
 
void Sample::test1() {
    printf("%s\n", "Hello World!");
}
 
void Sample::test2() {
}

test.cc

#include "sample.h"
 
Sample sample[10];
 
int main() {
    sample[0].test1();
    return 0;
}

このプログラムをコンパイルすると、下記の「invalid abstract type~」「because the following virtual functions are pure within~」というエラーに遭遇します。

% g++ test.cc sample.cc
test.cc:3:17: エラー: invalid abstract type 'Sample' for 'sample'
 Sample sample[10];
                 ^
In file included from test.cc:1:0:
sample.h:1:7: 備考:   because the following virtual functions are pure within 'Sample':
 class Sample {
       ^
sample.h:5:22: 備考:    virtual void Sample::test2()
         virtual void test2() = 0;
                      ^

2.原因

純粋仮想関数(pure virtual function)をもつクラスは抽象クラス(abstract class)となるので、その型のオブジェクトは定義できないようです。

3.対処

クラス定義をポインタ型にすることでこのエラーを回避できます。

#include "sample.h"
 
Sample *sample[10];
 
int main() {
    sample[0]->test1();
    return 0;
}

ポインタ型にするため、関数へのアクセスは"."ではなく、"->"に変更します。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

標準エラー出力をlessで表示する方法

March 3,2017 12:03 AM
Category:[Linux]
Tag:[Linux]
Permalink

標準エラー出力をlessで表示する方法を紹介します。

1.問題点

LinuxでC++のビルド作業をしており、gccコマンドで数千ほどのファイルのリンケージを実行してます。

で、実行すると案の定、大量のエラーが出力され、ターミナルのスクロールバーを戻しても先頭のエラーを確認することができません。

標準出力であればパイプでつないでlessで確認できるのですが、次のようなコマンドを実行しても標準エラー出力をlessで拾えません。

% make | less

ということで、標準エラー出力をlessで表示する方法を紹介します。

ここではmakeコマンドを例にしていますが、他のコマンドでもこのお作法が使えると思います。

2.標準出力と標準エラー出力の両方をlessで表示する

標準出力と標準エラー出力の両方をlessで表示するには、次のコマンドを実行します。

% make 2>&1 | less

コマンドの意味は次のとおりです。

まずmakeを実行します。

次の"2>&1"で、標準エラー出力(2)を標準出力(1)と同じファイルディスクリプタにリダイレクトします。

これで標準エラー出力をlessで拾えるようになります。

3.標準エラー出力だけをlessで表示する

標準エラー出力だけをlessで表示するには、次のコマンドを実行します。

% make 2>&1 > /dev/null | less

2のコマンドと異なるのは「> /dev/null」が追加されていることです。

これは標準出力(1)を/dev/nullにリダイレクトする(=破棄する)ことを意味します。

厳密には「1> /dev/null」と書きますが、「>」と書くと1を省略している意味になります。

Comments [0] | Trackbacks [0]

Chromeのタブ切り替えでリロードしない方法

March 2,2017 12:03 AM
Category:[Google Chrome]
Tag:[GoogleChrome]
Permalink

Chromeのタブ切り替えでリロードしない方法を紹介します。

1.問題点

いつ頃からか忘れましたが、Chromeで一度読み込んだページから他のタブに切り替え、再び元のタブに戻るとなぜかリロードされてしまうようになりました。

ページの内容を見比べたりするためにタブを頻繁に切り替える場合など毎回リロードされてしまうので、作業にかなり支障をきたしています。

ということで、Chromeのタブ切り替えでリロードしない方法を紹介します。

なお、Chromeのタブ切り替えでリロードされるのはメモリが少なくなったときのみのようです。

2.タブ切り替えでリロードしない方法

タブ切り替えでリロードしないようにするには、アドレスバーに「chrome://flags」を入力してリターン。

アドレスバー

「タブのメモリ解放を有効にする」項目を探します。

タブのメモリ解放を有効にする

プルダウンから「無効」を選択。

無効

「今すぐ再起動」をクリック。

今すぐ再起動

これでタブ切り替えをしてもリロードされなくなります。

なお、この機能を無効にすることでメモリリークする可能性もありますのでご注意ください。

Comments [0] | Trackbacks [0]

C++の可変長引数(va_list)の使い方

March 1,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C++の可変長引数(va_list)の使い方について紹介します。

1.可変長引数とは

可変長引数は、関数宣言および関数定義の最後の引数が省略記号(...)である場合、可変数の引数を受け取ることができるものです。

Func( int i, ... );

上記のように、省略記号が最後の引数で、省略記号(...)の前にカンマにある場合に限り、省略記号が可変長引数となります。

2.サンプル1

下記のサンプルは、関数「hoge」起動時の第1パラメータに可変長引数の総数「5」、第2パラメータ以降(=可変長引数)に「H」「e」「l」「l」「o」を渡し、表示させるものです。

#include <stdio.h>
#include <stdarg.h>
 
void hoge( int num, ...) {
    va_list args;
    va_start( args, num );
    for( int i = 0; i < num; ++i ) {
        printf( "%c\n", va_arg( args, char* ) );
    }
    va_end( args );
}
 
int main () {
   hoge( 5, 'H', 'e', 'l', 'l', 'o' );
}

各マクロの意味は次のとおりです。

va_start

可変長引数リストを初期化します。

  • 第1パラメータ:引数リスト
  • 第2パラメータ:指定した引数以降を引数リストに格納

サンプルでは、

va_start( args, num );

となっているので、引数リストargsに、num以降の引数を格納します。

va_arg

引数リストから順番に値を取得します。

  • 第1パラメータ:引数リスト
  • 第2パラメータ:取得時の型

サンプルでは、

va_arg( args, char* )

となっているので、引数リストargsからchar*型で値を取得します。

va_end

引数リストをクリアします。

  • 第1パラメータ:引数リスト

引数リストの操作が終わった後、この処理が必要なようです。

可変長引数マクロでは引数の個数を判断できないため、関数呼び出し時に引数の数を判断できる情報を第1パラメータで渡すのが定石のようです。

前述のサンプルでは、第1パラメータで指定された値をfor文の繰り返し回数に用いて、引数を取得・表示します。

    for( int i = 0; i < num; ++i ) {
        printf( "%c\n", va_arg( args, char* ) );
    }

3.サンプル2

前述のサンプルでは一意の型しか扱えないため、実践で使えそうなサンプルを作ってみました。

#include <stdio.h>
#include <stdarg.h>
 
void hoge( char *types, ...) {
    va_list args;
    va_start( args, types );
    for( int i = 0; types[i] != '\0'; ++i ) {
        printf( "%c:", types[i] );
        switch( types[i] ) {
        case 'i':
            printf( "%i\n", va_arg( args, int ) );
            break;
         case 'f':
            printf( "%f\n", va_arg( args, double ) );
            break;
         case 'c':
             printf( "%c\n", va_arg( args, char* ) );
             break;
         case 's':
             printf( "%s\n", va_arg( args, char* ) );
             break;
         default:
             break;
        }
    }
    va_end( args );
}
 
int main () {
   hoge( "ifcs", 30, 15.7f, 'a', "Hello World!" );
}

このサンプルでは、引数の数および型を第1パラメータで渡し、型によってswitch文で分岐させるようにしています。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

C/C++のオブジェクトファイルをldコマンドでリンクする方法

February 24,2017 12:33 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C/C++のオブジェクトファイルをldコマンドでリンクする方法を紹介します。

1.問題点

下記のプログラムを作りました。

sample.h

class Sample {
    public:
        Sample();
        void foo(int);
};

sample.cc

#include "stdio.h"
#include "sample.h"
 
Sample::Sample(){
}
 
void Sample::foo() {
    printf( "Hello, World!\n" );
}

test.h

class Test {
    public:
        Test();
        void hoge();
};

test.cc

#include "test.h"
#include "sample.h"
 
Test::Test(){
}
 
void Test::hoge() {
    Sample a;
    a.foo();
}
 
int main () {
   Test test;
   test.hoge();
}

これをコンパイルして、オブジェクトファイルsample.o、test.oを作ります。

% g++ -I. -c sample.cc test.cc

このあと、g++ではなくldコマンドでリンケージを実行すると、「`puts' に対する定義されていない参照です」というエラーになります。

% ld -o main sample.o test.o
ld: 警告: エントリシンボル _start が見つかりません。デフォルトとして 00000000004000b0 を使用します
sample.o: 関数 `Sample::foo()' 内:
sample.cc:(.text+0x1c): `puts' に対する定義されていない参照です

ちなみに、g++コマンドでは正常にリンクできます。

% g++ -o main sample.o test.o

色々調べてみて"-lc"および"-lm"オプションを追加してみたところ、下記のコマンドラインで実行ファイル作成までできました。

% ld -o main -lc -lm sample.o test.o

ただ、実行すると「-bash: ./main: /lib/ld64.so.1: bad ELF interpreter: そのようなファイルやディレクトリはありません」というエラーになってしまいます。

% ./main
-bash: ./main: /lib/ld64.so.1: bad ELF interpreter: そのようなファイルやディレクトリはありません

lddコマンドで使われているライブラリを調べてみました。

g++でリンクした実行ファイル

% ldd main
        linux-vdso.so.1 =>  (0x00007fff19ba3000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f21983a5000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f21980a3000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f2197e8c000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f2197acb000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f21986c2000)

ldでリンクした実行ファイル

% ldd main
        linux-vdso.so.1 =>  (0x00007ffd1fc4f000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f6f19b6f000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f6f1986d000)
        /lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f6f19f45000)

出力結果より、オプションで指定するライブラリが足りないようですが、具体的な指定方法が分かりません。

ということで、ldコマンドでリンクする方法を紹介します。

2.ldコマンドでリンクする

ldコマンドでリンクするには、一旦g++コマンドに"-v"オプションをつけてリンクします。

% g++ -v -o main sample.o test.o
組み込み spec を使用しています。
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
ターゲット: x86_64-redhat-linux
configure 設定: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
スレッドモデル: posix
gcc バージョン 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/
LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'main' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. sample.o test.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o

"-v"は、コンパイルの各ステージで実行されるコマンドを表示するオプションです。

で、上記の最後の行に表示された"/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2"に--helpをつけて実行すると、

% /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --help
Usage: collect2 [options]
 Wrap linker and generate constructor code if needed.
 Options:
  -debug          Enable debug output
  --help          Display this information
  -v, --version   Display this program's version number
 
Overview: http://gcc.gnu.org/onlinedocs/gccint/Collect2.html
Report bugs: <http://bugzilla.redhat.com/bugzilla>
 
使用法: /usr/bin/ld [options] file...
(後略)

どうやらこれがldコマンドらしいので、これに続く内容(「--build-id」以降)をまるっとコピーして、ldコマンドのオプションに利用します。

% ld -o main --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. sample.o test.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o

これで正常な実行ファイルが作成できました。

3.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

C++のswitch文で「crosses initialization of~」というエラーの対処

February 23,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C++のswitch文で「crosses initialization of」というエラーの対処方法について紹介します。

1.問題点

下記のサンプルプログラムを作りました。

sample.h

class Sample {
    public:
        Sample();
        void foo();
};

sample.cc

#include "stdio.h"
#include "sample.h"
 
Sample::Sample(){
}
 
void Sample::foo() {
    printf( "Hello World!\n" );
}

test.h

class Test {
    public:
        Test();
        void hoge(int);
};

test.cc

#include "test.h"
#include "sample.h"
 
Test::Test(){
}
 
void Test::hoge(int result) {
    switch (result) {
        case 0:
            break;
        case 1:
            Sample a;
            a.foo();
            break;
        default:
            break;
    }
}
 
int main () {
   Test test;
   test.hoge(1);
}

このプログラムをコンパイルすると、下記の「crosses initialization of」というエラーに遭遇します。

% g++ -g -w -ansi -fpermissive -I. test.cc sample.c
test.cc: メンバ関数 'void Test::hoge(int)' 内:
test.cc:13:20: エラー:   crosses initialization of 'Sample a'
             Sample a;
                    ^

2.原因

まず、switch文はcase内ではなく、switch全体でひとつのスコープとみなされます。

よって"case 1:"に実装された変数aのスコープはswitch文全体で有効になりますが、"case 1:"が実行されなかった場合、aの定義が行われないため、コンパイルエラーとなるようです。

今回はクラス定義が対象の処理でしたが、単なる変数定義でも同様のエラーが発生します。

3.対処

"case 1"全体をブロックで囲みます(括り方はさまざまですが少なくとも変数aがカッコで括ったブロック内にあること)。

void Test::hoge(int result) {
    switch (result) {
        case 0:
            break;
        case 1: {
            Sample a;
            a.foo();
            break;
        }
        default:
            break;
    }
}

これで変数のスコープがブロック内に閉じられます。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

C言語で「静的宣言の後に非静的宣言が続いています」というエラーになる場合の対処

February 22,2017 12:03 AM
Category:[C/C++]
Tag:[C/C++]
Permalink

C言語で「静的宣言の後に非静的宣言が続いています」というエラーになる場合の対処について紹介します。

1.問題点

下記のサンプルプログラムを作りました。

main.h

#include <stdio.h>
 
void hello_world(void);

main.c

#include <main.h>
 
int main(void) {
    hello_world();
    return 0;
}
static void hello_world(void) {
    printf( "Hello World!\n" );
}

hello.h

#include <stdio.h>
 
extern void hello_world(void);

hello.c

省略

これでmain.cをコンパイルすると、「静的宣言の後に非静的宣言が続いています」というエラーが発生します。

% gcc -I. main.c
main.c:8:13: エラー: 'hello_world' は静的宣言の後に非静的宣言が続いています
 static void hello_world(void) {
             ^
In file included from main.c:1:0:
./main.h:3:6: 備考: 前の 'hello_world' の宣言はここです
 void hello_world(void);
      ^

2.原因

externは、外部ファイルの関数を使うことを宣言したものです。

staticは静的な関数として定義する意味があり、定義されたファイル以外からは参照することができなくなります。

つまり、上記のプログラムは相反する指定をしていることによるエラーとなります。

C言語の仕様を調べていればこのような実装は通常行わないと思いますが。。。

3.対処

"static"を外せば正常にコンパイルできるようになります。

ちなみにg++でコンパイルすると、

% g++ -I.  main.c
main.c: 関数 'void hello_world()' 内:
main.c:8:29: エラー: 'void hello_world()' was declared 'extern' and later 'static' [-fpermissive]
 static void hello_world(void) {
                             ^
In file included from main.c:1:0:
./main.h:3:6: エラー: previous declaration of 'void hello_world()' [-fpermissive]
 void hello_world(void);
      ^

となり、コンパイルで"-fpermissive"を付与する指示が表示されます。

% g++ -I.  -fpermissive main.c
main.c: 関数 'void hello_world()' 内:
main.c:8:29: 警告: 'void hello_world()' was declared 'extern' and later 'static' [-fpermissive]
 static void hello_world(void) {
                             ^
In file included from main.c:1:0:
./main.h:3:6: 警告: previous declaration of 'void hello_world()' [-fpermissive]
 void hello_world(void);
      ^

エラーが警告になります。

-fpermissiveの意味はmanで調べると、

Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive allows some nonconforming code to compile.(不適合コードに関するいくつかの診断をエラーから警告にダウングレードします。したがって、-fpermissiveを使用すると、いくつかの非適合コードをコンパイルする。)

ということらしいです。

このオプションはg++のみ有効で、gccでは使えないようです。

Comments [0] | Trackbacks [0]

lessからvimやemacsに切り替える方法

February 17,2017 12:03 AM
Category:[Linux]
Tag:[Linux]
Permalink

lessからvimやemacsに切り替える方法を紹介します。

1.はじめに

lessコマンドでファイル閲覧中に"v"を押下するとviエディタに切り替わり、ファイルの編集が可能になります。

またエディタを終了するとlessに復帰するので非常に重宝しています。

ただデフォルト状態ではviしか起動せず、vimやemacsなど、他のエディタに切り替えることができません。

ということで、lessからvi以外のエディタに切り替える方法を紹介します。

2.vi以外のエディタに切り替える

vi以外のエディタに切り替えるには、環境変数VISUALに"vim"を設定します。

vimの場合

% export VISUAL="vim"

emacsの場合

% export VISUAL="emacs"

これで"v"を押下すると、指定したエディタに切り替わります。

VISUALは、lessで"v"を押下したときの起動エディタを指定するための環境変数です。

エディタへのパスが通っていない場合は、フルパスで指定します。

vimの場合

% export VISUAL="/usr/bin/vim"

emacsの場合

% export VISUAL="/usr/bin/vim"

エディタのパスは環境によって異なるかもしれないので、whichコマンドで確認してください。

3.ログイン直後に切り替える

上記の方法では環境変数を設定したターミナルでしか有効になりません。

常ににエディタを変更したい場合は、上記のexportコマンドをホームディレクトリの.bashrcに追記します。

これでログイン直後に設定が有効になります。

4.参考サイト

参考サイトは下記です。ありがとうございました。

Comments [0] | Trackbacks [0]

xhostコマンドで「unable to open display」となる場合の対処

February 15,2017 12:03 AM
Category:[Linux]
Tag:[Linux]
Permalink

xhostコマンドで「unable to open display」となる場合の対処方法を紹介します。

1.問題点

xhostコマンドを実行すると、「unable to open display ""」というエラーになってしまいます。

# xhost +
xhost:  unable to open display ""

ちなみにxhostはXサーバへのアクセスの許可・不許可を設定するコマンドで、"xhost +"で全てのクライアントに対してアクセス制限を解除します。

2.原因と対処

原因は、xhostを実行したターミナルで環境変数DISPLAYが設定されていないためです。

# env | grep DISPLAY
#

ということでxhost実行の前に、環境変数DISPLAYを設定します。

# export DISPLAY=:0.0
# env | grep DISPLAY
# DISPLAY=:0.0

この状態でxhostを実行します。

# xhost +
access control disabled, clients can connect from any host

DISPLAY変数の値":0.0"は、"localhost:0.0"と同じ意味です。

Comments [0] | Trackbacks [0]
 1  |  2  |  3  |  4  |  5  | All pages