2중 vector 를 포인터로 액세스할때 에러

jinserk의 이미지

아래 질문의 연장입니다. :( 이것때문에 계속 고생이네요.

class A {
    typedef std::vector<T> T_vec;
    typedef std::vector<T_vec> T_mat;
 
    T_mat x;
    B     b;
 
    A : b(&x) () {};
};
 
class B {
    typedef std::vector<T> T_vec;
    typedef std::vector<T_vec> T_mat;
 
    B(T_mat* px) { px->resize(10) };

2차원 matrix 표현을 위해 vector 를 위와 같이 선언해줬는데,
class B 에서 px->resize() 부르는 부분에서 access violation 이 발생합니다.
아무리 생각해도 잘모르겠네요.. 도움 부탁드립니다.

winner의 이미지

제가 알기로는 member 변수들의 생성순서는 정해져 있지 않은 것으로 아는데...
그래서 그런게 아닐까 싶다는...

terzeron의 이미지

class B에서 사용된 T가 명확하지 않은데요.
템플릿을 만드시는 건가요?

jinserk의 이미지

T 는 제가 만든 complex 데이터 형 template 클래스가 들어갑니다.
class A, B 가 템플릿은 아니지만 T = complex<double> 이라고 보시면 될듯..

Leo.

jinserk의 이미지

조금더 테스트를 해보았습니다.
원래 class A 역시 vector 에 들어가는 데이터 구조라.. 전체적으로 보면 아래와 같은 구조입니다.

......
std::vector<A> a_vec;
for (int i = 0; i < 3; i++) {
    A a(0);
    a_vec.push_back(a);
}
......
 
 
class A {
    typedef std::vector<complex<double> > cmplx_vec;
    typedef std::vector<cmplx_vec>        cmplx_mat;
 
    cmplx_mat buffer;
    B         b_module;
    int       m_x;
 
    A : b_module(&buffer) (int x)
    {
        m_x = x;
    }
};
 
class B {
    typedef std::vector<complex<double> > cmplx_vec;
    typedef std::vector<cmplx_vec>        cmplx_mat;
 
    B(cmplx_mat* px)
    {
        px->resize(10, cmplx_vec(10));
    }
};

이때 a_vec 에 들어가는 &buffer 를 찍어보니까, 모두 같은 주소를 갖고 있네요.
A a 를 만든다음 push_back 하니까 같은 주소로 매핑되나봅니다.

그래서 a_vec.resize(3) 과 같은 형식으로 바꾸고 class A 의 constructor 를
void initialize(int x) 와 같은 멤버 함수로 바꾼다음 a_vec[i].initialize() 를
부르는 식으로 바꿔봤는데, 이런 경우는 &buffer 가 모두 다른 값을 가지게 됩니다만,
역시나 resize 를 하면 segmentation fault 를 내버립니다.
class 의 멤버변수로 2중 vector 를 쓰면 문제가 되는걸까요? 난감하네요.

Leo.

obbaya의 이미지

C++이 객체를 생성하는 순서와

특히 객체 생성시 초기화 순서(콜론 초기화, 생성자 블럭 외 초기화, 생성자 블럭 내 초기화)를

찾아보시면 왜 메모리 접근 불가 가 되는지 알 수 있지 않을까요?

전 범인으로 몰고 계시는 2중벡터가 억울해 보이네요;

jinserk의 이미지

감사합니다.

2중벡터를 범인으로 의심하는(?) 이유는
MSVC 2008 에서 코드를 돌려보고 class B 에서 초기화된 px 의 참조 형태를 보니
allocator 가 vector<vector<complex<double> > > 형태가 아닌 complex<double> 의 형태로
되어 있었기 때문입니다.

일단 이 문제를 우회하는 방법으로 다시 코딩중이긴 합니다만.. 왜 안되는지 정말 궁금하네요.

Leo.

winner의 이미지

allocator라면
 allocator<vector<complex<double> > > 아닌가요?
allocator는 원소에 대해서 type 매개변수를 받을텐데요.
말씀하신대로라면 내부의 vector에 대한 allocator type 매개변수를 확인하신게 아닌가 싶네요.

winner의 이미지

윗글과 중복되었습니다.

yielding의 이미지

A(int x) : buffer(), b_module(&buffer)
{
  ...
}


이렇게 되야 하지 않나요?
명시적으르 buffer 객체를 먼저 초기화 하고 그다음 b_module을 초기화...

Life rushes on, we are distracted

Life rushes on, we are distracted

winner의 이미지

생성(초기화)순서는 불만을 가지고 있는 사람들이 좀 있는 사안이지만 그렇다고 꼭 순서에 따라 하나하나 초기화하는 것도 성능에 문제가 될 수 있습니다.

obbaya의 이미지

VC2008, gcc 4.1.2 에서 테스트를 해보니 초기화 순서는 컴파일러가 알아서 맞춰주는 것 같습니다.

하지만 상당히 식은 땀 나는 초기화 순서임에는 많은 분들이 동의하실 것 같고요 암튼,

고민이 깊어지실 것 같아 식사 후 에 테스트를 해보았는데요

#include

template
struct Complex {
T a_, b_;

Complex(T a, T b) : a_(a), b_(b) {}
};

class B {
typedef std::vector > T_vec;
typedef std::vector T_mat;

public:
B(T_mat *px) { px->resize(10); }
};

class A {
typedef std::vector > T_vec;
typedef std::vector T_mat;

T_mat x;
B b;

public:
A() : b(&x) {}

void add() { T_vec tmpTV; tmpTV.push_back(Complex(1, 2) ); x[0] = tmpTV; }
};

int main()
{
A a;
a.add();

return 0;
}

쓰신 내용에 맞춰서 해본다고 했는데 위 코드는 실행에 문제가 없네요

아마도 제가 내용을 잘 못 파악하고 있는 것 같은데

실제 문제가 생기는 코드를 발췌해 주시거나 위 코드를 인용해서 의도를 다시 제시해주시면

저도 고민해볼께요

아 그리고 '꼭 순서에 따라 하나하나 초기화하는 것도 성능에 문제가 될 수 있습니다.'

이 부분에서 buffer() 는 직접 명시하지 않아도 컴파일러가 넣어주는 부분이니

코드량에 따른 성능을 얘기하시는 거라면 아닌 것 같고 초기화 순서에 따른 문제를 예방하는 측면에서는

오히려 원 코드보단 대단히? 좋은 코드가 아닐까요;

jinserk의 이미지

아아.. 감사합니다.
일단 원코드를 발췌해드리긴 어렵습니다. 곁가지가 달린 코드량이 엄청 많은데다
보안상 유출도 안됩니다. :(
사실 제가 올려드린 코드를 회사의 다른 분께서 테스트해보셨는데 이상없이 실행되더라 하셔서
참 난감했습니다.
가능한대로 원 문제가 발생하는 코드를 따로 만들어 보겠습니다. (가능할지 모르겠네요. ㅜㅠ)

Leo.

winner의 이미지

귀찮더라도 같은 class 내에서 한 member변수를 다른 member변수의 초기화과정에 넣고자 하신다면 상속을 쓰시면 원하시는대로 될 것 같습니다.

기반 class 부분이 파생 class 부분보다 먼저 생성되도록 되어 있으니까요.
기반 class 부분의 member 변수를 파생 class 부분의 member 변수의 생성자 매개변수로 활용하는 것은 올바른 방법입니다.

저라면 그냥 기본생성자로 생성하겠지만 말이죠.
아휴, 사용하지 않을 기반 class 만드는 귀찮음을 어떻게 하남?

winner의 이미지

좀 찾아봤는데 C++ 의 class member 변수 초기화 순서는 선언순서를 따른다고 하네요.
초기화목록에 명시한 순서와는 상관이 없다고 합니다.
따라서 발제자가 처음 작성하신 code에 문제가 있고, 그것이 초기화순서에 의한 것이라면
그것은 compiler의 문제입니다.
그 문제가 분명하다면 compiler를 바꾸시던가 compiler 문제를 피해갈 수 있는 방식으로 작성해야겠네요.

성능문제를 이야기한 것은 초기화순서를 분명히 하지 않고, 동시 초기화가 가능하게 되어 있는 줄 알았기 때문이었는데,
사실 병렬처리의 가능성은 compiler가 판단할 문제이므로 문제될 것이 없겠네요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.