環境は

mac osx 10.3.9
gcc/g++ は 3.3です.

あるc++プログラムをコンパイルしてgdbでdebugすると以下のmessageが出ます.
vectorが悪さをしていると思うのですが, 対処法が分かりません.
アドバイスよろしくお願いします.

Program received signal EXC_BAD_ACCESS, Could not access memory.
0x05c79fdc in std::__default_alloc_template<true, 0>::allocate(unsigned long) () at /usr/include/gcc/darwin/3.3/c++/bits/stl_vector.h:525
525 operator[](size_type __n) const { return *(begin() + __n); }
(gdb) where
#0 0x05c79fdc in std::__default_alloc_template<true, 0>::allocate(unsigned long) () at /usr/include/gcc/darwin/3.3/c++/bits/stl_vector.h:525

以下長過ぎるので, 後ほどのせます.

回答の条件
  • 1人3回まで
  • 登録:
  • 終了:2007/05/15 01:20:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:ivory-star No.1

回答回数29ベストアンサー獲得回数3

ポイント27pt

今、手元に環境がないので、あくまで予想ですが…

vectorで準備された配列のサイズを超えてアクセスしているのでは?

id:Q-tarou

返信ありがとうございます

実は, このプログラムは, この環境でmemory leakを起こしていて, それが原因で, 回答のようになっているかもしれません.

Vine Linux 4.0

gcc/g++ 3.4.4

だと, valgrind 3.2.3ではmemory leakもなく, gdbでこのようなmessageは出ません.

なお, 以下に gdb のlog を...

<---ココから

#1 0x05cb978c in std::vector<int, std::allocator<int> >* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<std::vector<int, std::allocator<int> > const*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >, std::vector<int, std::allocator<int> >*>(__gnu_cxx::__normal_iterator<std::vector<int, std::allocator<int> > const*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >, __gnu_cxx::__normal_iterator<std::vector<int, std::allocator<int> > const*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >, std::vector<int, std::allocator<int> >*, __false_type) (__first={<iterator<std::random_access_iterator_tag,std::vector<int, std::allocator<int> >,int,const std::vector<int, std::allocator<int> >*,const std::vector<int, std::allocator<int> >&>> = {<No data fields>}, _M_current = 0x5cd903c}, __last={<iterator<std::random_access_iterator_tag,std::vector<int, std::allocator<int> >,int,const std::vector<int, std::allocator<int> >*,const std::vector<int, std::allocator<int> >&>> = {<No data fields>}, _M_current = 0x45f9eb0}, __result=0x36e94a8) at /usr/include/gcc/darwin/3.3/c++/bits/stl_alloc.h:232

ココマデ -->

2007/05/08 11:54:48
id:Bookmarker No.2

回答回数191ベストアンサー獲得回数34

ポイント27pt

# 具体的なコード例がないので推測で書きますが…

前回のご質問の補足として私の日記に書きましたが、GCC 3.3 系列の std::allocator にはバグがあるのではないかと思われます。

どうしても 3.3 系列を使う必要があるのでなければ、3.4 系列以降を使った方が良いと思います。

どうしても 3.3 系列を使う必要があるのなら、独自のアロケーターを指定するか、std::allocator を修正してみてはいかがでしょうか。

id:Q-tarou

ありがとうございます. やはりそうですか.

実際, gcc/g++を3.4.6に上げると, 上のようなmessageは出ません.

実は, 元々は, ある数値計算用softwareからc++を呼び出していて, そのsoftwareでは, この環境ならgcc/g++は3.3で大丈夫だと言っていて, やっぱり自分のc++に問題があるのかなと悩んでいました. が, これではっきりとgcc/g++の方に問題があるという自信が持てました.

2007/05/08 19:05:27
id:Bookmarker No.3

回答回数191ベストアンサー獲得回数34

ポイント26pt

gcc/g++の方に問題がある

当方の環境では、gdb でご質問のようなエラーを再現できませんでしたので断言はできませんが、ご質問の環境で次のような単純なアロケーターを指定して、ご質問のようなエラーにならなければ、より可能性が高くなると思います。

(当方の環境では、これで valgrind でメモリーリークは検出されなくなりました。)


当方の環境:

  • FreeBSD 6.2-RELEASE-p4
  • g++ (GCC) 3.3.6
  • GNU gdb 6.1.1
  • valgrind-352_6

アロケーターの例:

my_allocator.hpp

#ifndef MY_ALLOCATOR_HPP
#define MY_ALLOCATOR_HPP


#include <cstddef>
#include <limits>


template<typename T>
class my_allocator
{
  public:
    typedef std::size_t         size_type;
    typedef std::ptrdiff_t      difference_type;
    typedef T                   *pointer;
    typedef const T             *const_pointer;
    typedef T                   &amp;reference;
    typedef const T             &amp;const_reference;
    typedef T                   value_type;

    template<typename U>
    struct rebind
    {
        typedef my_allocator<U> other;
    };

    my_allocator() throw() {}

    my_allocator(const my_allocator &amp;) throw() {}

    template<typename U>
    my_allocator(const my_allocator<U> &amp;) throw() {}

    ~my_allocator() throw() {}

    pointer address(reference value) const {
        return &value;
    }

    const_pointer address(const_reference value) const {
        return &value;
    }

    size_type max_size() const throw() {
        return std::numeric_limits<std::size_t>::max() / sizeof(T);
    }

    pointer allocate(size_type num, const void * = 0) {
        return static_cast<pointer>(::operator new(num * sizeof(T)));
    }

    void construct(pointer p, const T &amp;value) {
        ::new(p) T(value);
    }

    void destroy(pointer p) {
        p->~T();
    }

    void deallocate(pointer p, size_type) {
        ::operator delete(p);
    }
};

template<typename T1, typename T2>
bool operator==(const my_allocator<T1> &amp;, const my_allocator<T2> &amp;) throw() {
    return true;
}

template<typename T1, typename T2>
bool operator!=(const my_allocator<T1> &amp;, const my_allocator<T2> &amp;) throw() {
    return false;
}


#endif // !MY_ALLOCATOR_HPP

使用例:

#include <vector>
#include "my_allocator.hpp"
#include <iostream>

#define DEFAULT_ALLOCATOR       my_allocator
//#define DEFAULT_ALLOCATOR     std::allocator
typedef std::vector<int, DEFAULT_ALLOCATOR<int> >               vec_int;
typedef std::vector<vec_int, DEFAULT_ALLOCATOR<vec_int> >       vec_vec_int;

int main()
{
    vec_vec_int obj;
    for ( vec_vec_int::size_type i = 0; i < 128; ++i ) {
        obj.push_back(vec_int());
        for ( vec_int::size_type j = 0; j < 256; ++j ) {
            obj[i].push_back(j);
        }
    }
    for ( vec_vec_int::size_type i = 0; i < obj.size(); ++i ) {
        std::cout << "---- " << i << "\n";
        for ( vec_int::size_type j = 0; j < obj[i].size(); ++j ) {
            std::cout << obj[i][j] << ",";
        }
        std::cout << std::endl;
    }
}

そのsoftwareでは, この環境ならgcc/g++は3.3で大丈夫だと言っていて

バージョンを変えられそうもない状況のようですね。

となると、次のような対策が考えられますが、(2)が比較的簡単かつ影響が少ないのではないかと思います。

(std::allocator がバグっているという前提)

(1)std::allocator を修正する

(2)独自のアロケーターを指定する

(3)std::allocator を、独自のコード(アロケーター)に置き換える

(4)STL を STLport 等に替える

  • id:Q-tarou
    返事が遅くなってすみません.

    ありがとうございます. 現状では, gcc/g++のversionを上げることで対応しようと考えております.

    提供していただいたプログラムを利用したいのですが, かなり多数での箇所を書き換えなければならず, その手間を考慮すると現時点では, 利用しない方向で調整しています.

    いろいろ, 丁寧にしていただいて本当にありがとうございます. また, 進展がありましたら報告いたします.

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません