

助けてください。自分で定義した構造体( elmCom )のvectorにアクセスしようとすると、突然プログラムが終了してしまうのです。vector(
名前はelcomでとてもまぎわらしい
)はヘッダーファイルで定義したのち、ObdCapture.cpp内のコンストラクタでメモリを確保して、initメソッドでxml（大体800行くらい）
からデータをelcomにpush_backしています。push_backしたのちにelcom.size()でサイズが確認できるのですが、vector内部の構造体の値を参照しようとしたり、イテレータを使ってアクセスしようとするとそのように突然終了してしまうようです。エラーは特に出力されませんでした。  
セグメンテーションエラーならば普通に出るようです。

開発環境はraspbian(raspberry pi)です。稚拙な文とコードで申し訳ございません。  
どうか宜しくお願い致します。

main.cpp

[code]

    #include <stdio.h>
    #include "ObdCapture.h"
    
    int main(){
    
    ObdCapture *oc = new ObdCapture();
    
    oc->init();
    oc->set_addr((char*)"00:00:00:08:A5:C6"); 
    
    int a[] = {1, 2, 3, 4, 5};
    if(oc->setMonitored(a, sizeof(a)/sizeof(a[0])) || oc->connectElm()){
        oc->setFile("log");
        if(oc->f_con_write()){
            std::cout << "end" << std::endl;
        }
    }
    
    //メモリ解放
    delete oc;
    }
    
[/code]

Obd_Capture.h

[code]

    #ifndef _OBDCAP_H_
    #define _OBDCAP_H_
    #include <vector>
    #include <string>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/rfcomm.h>
    #include <boost/property_tree/ptree.hpp>
    #include <fstream>
    
    typedef struct elmCom{
                char* code;
                int num;
                int bit;
                int mode;
    }elmCom;
    
    class ObdCapture
    {
    public:
    // Constructor
        ObdCapture();
    // Destructor
        ~ObdCapture();
        void init();
     // モニターするOBDコード
        int setMonitored(int a[], int l_length);
    // モニターしているOBDコード一覧の取得
        std::vector<elmCom> getMonitored();
    // 接続の確認
        int connectElm();
        void set_addr(char* addr);
        std::string get_addr();
        std::string getFile();
        void setFile(std::string fname);
        // fileへの読み書き
        int f_con_write();
    
    private:
        std::string fname; // ファイルネーム
        time_t t;
        std::vector<elmCom> cap_register;
        std::vector<elmCom> elcom; // obdPID一覧(xmlからのよみこみ担当)   
        char can_buf[1025];
        sockaddr_rc addr;
        char buf[1025]; // 受信用バッファ
        int s, status, server;
        char dest[18];
        std::string path; // ファイルパス 
        std::ifstream fin; // 入力ストリーム
        std::ofstream fout;     // 出力ストリーム
        std::string file_path;
        unsigned int flags; // 処理の順序が正しく行われているかのフラグ
        boost::property_tree::ptree pt; // xmlのツリー
    };
    
    #endif //_OBDCAP_H_
    
[/code]

Obd_Capture.cpp

[code]

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/rfcomm.h>
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <time.h>
    #include <boost/foreach.hpp>
    #include <boost/property_tree/xml_parser.hpp>
    #include <boost/property_tree/ptree.hpp>
    #include <boost/optional.hpp>
    #include "ObdCapture.h"
    
    using namespace std; 
    using namespace boost::property_tree;
    
    // ファイル操作及びブルートゥースの通信
    #define BIT(num)                 ((unsigned int)1 << (num))
    
    #define AVA_BLUETOOTH            BIT(0) // ブルートゥースの接続が確立
    #define AVA_FILE                 BIT(1) // 書き込みファイルの準備
    #define AVA_OBD_CODE             BIT(2)  // OBD-IIの取得コマンド
    #define AVA_CAP_OBD              BIT(3) // OBD-IIのキャプチャ
    #define AVA_BT_ADDR              BIT(4) // 取得アドレスの準備
    #define ERR_BLUE_NOT_READ        BIT(5)
    
    
    ObdCapture::ObdCapture(): elcom(138), cap_register(138)
    {   
        elmSwitch = 0;
        addr = (sockaddr_rc){ 0 }; // sockaddr_rc addr
        flags = 0;
        t = time(NULL);
        memset(buf, '\0', sizeof(buf)); // bufの初期化
    }
    
    ObdCapture::~ObdCapture()
    {
        cout << "デストラクタ呼び出し\n";
        if (fname.empty()) {
            fout.close();
        }
        if (flags & AVA_BLUETOOTH) {
             close(s);
        }
    }
    
    void ObdCapture::init() {
    ptree ptt;
    read_xml("obd_config.xml", ptt); // Boostのxmlライブラリ
    std::string str;
    int num;
    int bit;
    int mode;
    int i = 0;
    BOOST_FOREACH(const ptree::value_type& pct, ptt.get_child("pids")){                     
            str = pct.second.get<std::string>("code");
            num = pct.second.get<int>("num");
            bit = pct.second.get<int>("bit");
            mode = pct.second.get<int>("mode");
            char* code = new char[str.size() + 1]; // メモリ確保
            std::strcpy(code, str.c_str()); // コピー
            elmCom elc = {code, num, bit, mode};
            cout << "elc is " << elc.code << endl;
            elcom.push_back(elc);
            cout << elcom.size() << endl;
            cout << i++ << endl;
    // 再代入
    }
    if ((flags & AVA_OBD_CODE) == 0) {
        flags += AVA_OBD_CODE;
        cout << "AVA_OBD_CODE"  << endl;
    }
    //cout << elcom.at(0).code << endl; <- こういうことするとエラー  
    }
    /* 以下略　*/
    
[/code]


CC BY-SA 3.0
2016-12-14T14:30:47.157
31152
2016-12-14T16:30:54.783
19920
question
c++ linux ポインタ
vector内の構造体にアクセスすると落ちる


`ObdCapture`クラスのコンストラクタで`elcom(138)`となっていますが，これだとメンバ変数`elcom`には`pushback`する前にすでに不定値の`code`を含んだ`elmCom`オブジェクトが先頭から138個含まれることになります．  
この不定値の`code`を文字列として読み出そうとする（すなわち`cout << elcom.at(0).code <<
endl;`などとする）と高確率で`code`の不定値は無効なメモリ領域を指しているので，プログラムがクラッシュします．  
`elcom(138)`の部分を`elcom()`にしたら直るはずです．

質問とは直接関係ありませんが，アドバイスさせてください．  
コードについてそれなりの量を書けるようですし，必要なライブラリ等を調べる能力もあると見受けました．時間をとってきちんとしたコードの書き方やテクニック等を学ぶと今よりもだいぶプログラミングが楽になるかと思います．書籍であれば「Effective
C++」や「C++ Coding Standards」等を読むのがおすすめです．特にリソース管理についてよく読んでみてください．


CC BY-SA 3.0
2016-12-14T16:30:54.783
31156
2016-12-14T16:30:54.783
4548
31152
answer