• 締切済み

C++のSTL mapを使用するとセグメンテーション違反となる

こんにちは。C++でSTLのmapの簡単な使用テストを以下のプログラムで行っており、動作確認ができました。 /* Assoc_array.c */ #define MAIN // (#include省略) using namespace std; namespace Usefuls { class Assoc_array_str { private: map<string, string> _h; public: void set(string key, string val); string get(string key); }; void Assoc_array_str::set(string key, string val){ _h.insert(pair<string, string>(key, val)); } string Assoc_array_str::get(string key){ map<string, string>::iterator p; p = _h.find(key); return p->second; } } #ifdef MAIN int main(){ Usefuls::Assoc_array_str assoc; assoc.set("Konnichiwa", "Hello"); cout << assoc.get("Konnichiwa") << endl; return 0; } #endif /* ここまで */ しかし、これを以下のように他のファイルから呼び出すと(先頭の#define MAINを#undef MAINに変えます)、「セグメンテーション違反です」というメッセージが出てしまいます。 /* Aa_test1.c */ #include <iostream> using namespace std; namespace Usefuls { class Assoc_array_str { public: void set(string, string); string get(string); }; } int main(){ Usefuls::Assoc_array_str assoc; assoc.set("Konnichiwa", "Hello"); cout << assoc.get("Konnichiwa") << endl; return 0; } /* ここまで */ コンパイル方法は以下の通りです。 g++ -c Assoc_array.c g++ Aa_test1.c Assoc_array.o また、使用プラットホームはLinuxのCentOS 4.3です。 原因が分かる方、ご回答をよろしくお願いします。

みんなの回答

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

デバッガで追ったわけではありませんが... Assoc_array_strのクラス指定子が、翻訳単位間で矛盾しているようです。 単一定義規則違反ですので、未定義の動作になったのではないでしょうか。

Mephyl
質問者

お礼

早速のご回答をありがとうございました。 Assoc_array.cと統一する形でAa_test1.cのAssoc_array_strを以下のように書き変えたところうまく行きました。 namespace Usefuls { class Assoc_array_str { private: map<string, string> _h; public: void set(string, string); string get(string); }; } 利用する可能性のある変数や関数だけを宣言すればいいのかと思っていましたが、全部宣言しなければならないのですね。

関連するQ&A

  • map(STL)でinsertを行いたいですが、成功できないでいます。

    皆さん、こんにちは。 このほど、STLのMAPを勉強しだしたものですが、 もっと基本的な、 C++の事でつまずいてしまいました。 keyとvalueのセットを 登録したり、 取得したりするソースを書いています。 下記ソースにありますとおり、 getの指示を出した際は、 通常、find(key)を行い、 valueを得るのですが、 仮にfindにて意図するvalueが見つからなかった場合には、 MySQLから意図するkeyに対応するvalueを 取ってこようと思っています。 そして、MySQLからvalueを取得した後は、 「m1.insert」にて 取得したその「value」と「key」のセットを insertを行う事で、 コンテナに登録作業をしたいつもりなのです。 どんな1行を足せばいいでしょうか? ずばりの答えでなく、 ユルメな方針のアドバイスでも いただけるとありがたいです。 ================================================================= virtual void put(key_type key, value_type val) { m1.insert(std::make_pair(key, val)); } virtual void get(key_type key) { typename container_type::iterator iterator = m1.find(key); if (iterator != m1.end()) { CTL_INFO("", "[info] Got the value ."); } else { /* ここでMySQLへ接続を行う*/ char query[256]; std::stringstream keystream ; keystream << key; std::string key1 = keystream.str().c_str(); if(sprintf(query, "select value_dht from table_name where key = ('%s')",keystream.str().c_str())); mysql_query(conn, query); res = mysql_use_result(conn); //get the results while ((row = mysql_fetch_row(res)) != NULL){ std::stringstream keydb2stream ; key2stream << row[0] ; std::string val1 = key2stream.str().c_str(); } /* ここで、MySQLから得たvalについて、      上記「virtual void put」のように「m1.insert」を行いたい。 それにより、returnで再度virtual void getへ移動した際には、     「m1.find(key)」を成功させたいです。*/ } return 0; }; ================================================================= また、間違っているかもしれませんが、 試しに、 「return 0」の2行上で、 次の1行を入れてみたのですが、 コンパイル時にエラーが出て怒られて失敗をしてしまいました。 「virtual void put」の部分で行っているinsertと、 同じ内容の文字列を同じようにinsertしているのに、 今回は怒られてしまうのかも、 よく分かりませんでした。 的外れな対応でしたらすいません。 ======================================================== m1.insert(std::make_pair(keystream.str().c_str(), key2stream.str().c_str())) ======================================================== error: cannot convert ‘const char*’ to ‘sc::basic_message_cons<sc::basic_message<void, char> >*’ in initialization

  • ofstream::getがおかしい!

    ofstream::getの動作がおかしいのです #include <string> #include <iostream> #include <fstream> using namespace std; void main(void) { ifstream ifs; ofstream ofs; string str; char c; str="abc"; cout<<"before str: "<<str<<endl<<endl; ofs.open("gomi");ofs<<str;ofs.close(); ifs.open("gomi");for(str="";ifs.eof()==0;str+=c)ifs.get(c);ifs.close(); cout<<"after str: "<<str<<endl<<endl; } の結果が before str: abc after str: abcc になります 最後のcは何でつくのでしょうか? 回避する方法を教えてください

  • STL mapでアクセス違反

    VC++2005 Express Editionを使用しています。 (Platform SDKを別途インストールしています。) STL mapの変数を宣言すると、その部分でアクセス違反が発生します。 これだけのコードも動きません。 #include <map> using namespace std; int main() { map<int, int> m; m.insert(pair<int, int>(0,10)); return 0; } グローバル宣言するれば、実行直後に止まります。 なにか対策があればよろしくお願いします。

  • C++でSTLを使った文字列操作

    C++素人です。 第一引数で指定するファイルパスの 拡張子を.datに変更する関数を作っていますがうまくいきません。 STLの使い方が悪いのでしょうか? #include <string.h> using namespace std; char *exchange(const char *fname) { char *file; char *ex; string str; str = fname; ex = ".dat"; str.erase(str.find_last_of('.')+1); file = strcat(str, ex); return file; } int main(int argc, char *argv[]) { char *file = exchange(argv[1]); return 0; }

  • C++

    C++で書いた下記のプログラムが、文字の入力が1023個までなら実行されますが、1024個を超えると実行されません。なぜだか分かる方、教えてください。 #include <iostream> #include <string> using namespace std; int main(void) { string Str; cin >> Str; cout << "here"; }

  • C++ の map についてです

    C++の初心者です。よろしくお願いします。 DirectXを使っていて簡単なゲームを作っていまして、 mapを使っていると、このようなエラーが出てしまいどうしても理由わかりませんでした。 class D2DMap : public GameTexture{ protected: GameTexture** CopyTexture; int MaxMass; int WidthMass; int HeightMass; int WidthMassPixel; int HeightMassPixel; int MassInfo[30][30]; public: D2DMap(); virtual ~D2DMap(); HRESULT LoadMapTexture(int widthmass, int widthmasspixel,int heightmass, int heightmasspixel, const char* FileName, D3DCOLOR color); HRESULT LoadTextMass(const char* FileName); int GetWidthMassPixel(){ return WidthMassPixel;} int GetWidthMassNum(){ return WidthMass;} int GetHeightMassPixel(){ return HeightMassPixel;} int GetHeightMassNum(){ return HeightMass;} int GetMassInfo(int x, int y){ return MassInfo[y][x];} void DrawMap(D3DCOLOR color); void DrawCopyMap(D3DCOLOR color); void SetCopyTex(GameTexture* copy){ CopyTexture= &copy;} void Delete(){} }; map<string , D2DMap*> MapBox; と定義して string Name="--------"; D2DMap map; MapBox.insert( map<string, D2DMap*>::value_type(Name, &map)); としたとこと error C2275: 'std::string' : この型は演算子として使用できません 'std::string' の宣言を確認してください。 error C2059: 構文エラー : '>' error C2039: 'value_type' : '`global namespace'' のメンバではありません というエラーが出てきました。 mapのfind や iterator は可能なのですがinsertの場合エラー となり、理由が全く分かりません。詳しい方アドバイスをお願いしたい のですが、よろしくお願いします。 VC++2008 を使っています。

  • C++

    今、下のようなプログラムを作っています #include <iostream> #include <iostream> using namespace std; int i=0, c=0, n; char str[10]; class X16karax10{ //16進から10進ヘ public: void keisan(); }; void X16karax10::keisan(void){ cout<<"16進を入力して下さい"<<endl; cout<<"英数字は大文字で入力してください(F→○ f→×)" <<endl; scanf("%s",str); while(str[i] != '\0'){ n = n * 0x10; c = str[i++]; if((c >= '0') && (c <= '9')){ n += c - '0'; } else if((c >= 'A') && (c <= 'F')){ n += c - 'A' + 10; } } cout<<("%d\n",n)<<"です\n"<<endl; } int main(){ for(i=0; ; i++){ X16karax10 p; p.keisan(); } } 16進を十進に変えるものなのですがreturn 0を使うと「X16karax10::keisan()' は値を返せない」と、でてしまうのですがどうしたらよいでしょうか?

  • C++ 2次元配列について 【 初心者です 】

    こんにちは.C++初心者です. 以下のプログラムは, オブジェクトの2次元配列の作成と そのアクセスをポインタで行うことを 目的としています. 以下の□■部が質問箇所です. なぜobをsamp型でキャストするのか分かりません. obはすでにsamp型で宣言しているのに… それと※部において 2度目のp++処理について教えていただきたいです. メモリーイメージを書いてもらえると ありがたいです。 よろしくおねがいします。 #include <iostream.h> using namespace std; class samp { int a; public: samp(int n) { a = n; } int get_val() { return a; } }; int main(void) { samp ob[3][2] = { 1, 2 3, 4, 5, 6 }; int i; samp *p; // □■□■□■□■ p = (samp *) ob; for(i = 0; i < 3; i++) { cout << p->get_val() << ' '; p++; ※ cout << p->get_val() << endl; ※ p++; } cout << endl; return 0; } }

  • C++ 動的確保について

    学校の演習課題で「クラス Array のメンバ変数を以下のように変更して,配列のサイズを実行時に決められるようにしたい.コンストラクタを適切に修正しなさい.配列のサイズはコンストラクタの引数で指定できるようにすること.main 関数内のオブジェクトの宣言部分を適当に変更して動作を確認しなさい.」という課題が出ました。 指示のメンバ変数の変更は、sizeを定数にしていたものを変数にし、arrayを配列からポインタにする点です。 もとのプログラムはI、私がいじったものがIIです。どうにもセグメンテーションフォルトから抜け出せなくて困っています。どのようにしたら題意のプログラムになるのでしょうか? よろしくお願いします。 ここからI~ #include <iostream> using namespace std; class Array{ private: const static int size = 6; int array[size]; public: Array( ); int getSize( ); void put( int index, int data ); int get( int index ); void show( ); }; Array::Array( ) { for ( int i = 0; i < size; i++ ) { array[i] = 0; } } int Array::getSize( ) { return size; } void Array::put( int index, int data ) { array[index] = data; } int Array::get( int index ) { return array[index]; } void Array::show( ) { cout << "| "; for ( int i = 0; i < getSize( ); i++ ) { cout << get(i) << " | "; } cout << endl; } int main( ) { Array array1; array1.put(1, 2); array1.put(4, 1); array1.show( ); return 0; } ~ここまでI ここからII~ #include <iostream> using namespace std; class Array{ private: int size; int *array; public: Array(int s); ~Array(); int getSize(); void put(int index, int data); int get(int index); void show(); }; Array::Array(int s) { size = s; array = new int; for (int i = 0; i < size; i++) { *array = 0; array++; } array -= size; } Array::~Array() { delete[] array; cout << "デストラクタが呼ばれました。配列の要素数分のメモリを開放します." << endl; } int Array::getSize() { return size; } void Array::put(int index, int data) { *(array + index) = data; } int Array::get(int index) { return *(array + index); } void Array::show() { cout << endl << "| "; for (int i = 0; i < getSize(); i++) { cout << get(i) << " | "; } cout << endl; } int main() { int s = 0; cout << "確保するサイズを入力してください:"; cin >> s; Array array1(s); array1.put(1, 2); array1.put(4, 1); array1.show(); return 0; } ~ここまでII

  • C/C++関数間でのStringクラスの扱い

    以下のようなコードを実行してみましたが思い通りに動いてくれません. "sample"という文字列がstrへとコピーされると思ったのですが. stringクラスのc_str()メソッドはconst char*だと言っているので無理矢理キャストしたのが原因でしょうか.stringクラスは記憶領域を自動で変更してくれるのではないのですか.それともこの挙動は仕様ですか. -------- 以下コード -------- #include <iostream> #include <string> using namespace std; int func(char *); int main(void) {     string str("");     func((char *)str.c_str());     cout << "String: " << str << endl;     return EXIT_SUCCESS; } int func(char *buf) {     buf = "sample";     return 0; } -------- 以上コード --------