سؤال

أنا أواجه قضية مؤشر محبط للغاية. سبق أن نشرت هنا:صعب: التعامل مع مؤشرات متداخلة بعمق في C ++

لكن هذا المنشور أصبح طويلاً بشكل مفرط وهو لا معنى له ، لذلك اخترت إعادة النشر بمزيد من التفاصيل.

إليكم ملف Header الذي يحدد الأنواع الخاصة بي:

#include <string>
#include <vector>
#include <sstream>
#include <iostream>

#define USE_3D_GEOM
//#define USE_2D GEOM

#define DEBUG

#ifdef USE_3D_GEOM
 #define DIMENSIONS 3
#elif USE_2D_GEOM
 #define DIMENSIONS 2
#else
 #define DIMENSIONS 1
#endif

#ifndef _COMMON_H
#define _COMMON_H

template<class T>
inline T from_string(const std::string& s)
{
     std::istringstream stream (s);
     T t;
     stream >> t;
     return t;
};

template <class T>
inline std::string to_string (const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}

enum e_ensemble_kind 
{
  MICROCANONICAL,
  CANONICAL,
  NVT,
  GRAND_CANONICAL,
  NPT,
  NVE
};

enum e_potential_kind 
{
  HARD_SPHERE,
  SQUARE_WELL,
  LENNARD_JONES
};

enum e_file_types
{
  MC_SIMPLE,
  NAMD,
  GROMACS,
  CHARMM
};

#ifdef USE_3D_GEOM
typedef struct s_coordinates t_coordinates;
#endif

#ifdef USE_2D_GEOM
typedef struct s_coordinates t_coordinates;
#endif

typedef struct s_particle t_particle;

typedef struct s_bond t_bond;

typedef struct s_angle t_angle;


typedef struct s_dihedral t_dihedral;

typedef struct s_molecule t_molecule;

typedef struct s_lj_param t_lj_param;

typedef struct s_bond_param t_bond_param;

typedef struct s_angle_param t_angle_param;

typedef struct s_dih_param t_dih_param;

typedef struct s_lookup_tab t_lookup_tab;

#ifdef USE_3D_GEOM
struct s_coordinates
{
  double x;
  double y;
  double z;

  s_coordinates& operator+(const s_coordinates &to_add)
  {
    x += to_add.x;
    y += to_add.y;
    z += to_add.z;
    return *this;
  }
  s_coordinates& operator-(const s_coordinates &to_subtract)
  {
    x -= to_subtract.x;
    y -= to_subtract.y;
    z -= to_subtract.z;
    return *this;
  }
  s_coordinates& operator=(const s_coordinates &to_assign)
  {
    x = to_assign.x;
    y = to_assign.y;
    z = to_assign.z;
    return *this;
  }
  bool operator==(const s_coordinates &to_assign)
  {

    return x == to_assign.x && y == to_assign.y && z == to_assign.z;
  }
};
#endif

#ifdef USE_2D_GEOM
struct s_coordinates
{
  double x;
  double y;

  s_coordinates& operator+(const s_coordinates &to_add)
  {
    x += to_add.x;
    y += to_add.y;
    return *this;
  }
  s_coordinates& operator-(const s_coordinates &to_subtract)
  {
    x -= to_subtract.x;
    y -= to_subtract.y;
    return *this;
  }
  s_coordinates& operator=(const s_coordinates &to_assign)
  {
    x = to_assign.x;
    y = to_assign.y;
    return *this;
  }
  bool operator==(const s_coordinates &to_assign)
  {

    return x == to_assign.x && y == to_assign.y;
  }
};
#endif

typedef struct s_particle
{
  t_coordinates position;
  double charge;
  double mass;
  std::string name;
  std::vector<t_lj_param>::iterator my_particle_kind_iter;

  s_particle& operator=(const s_particle &to_assign)
  {
    position = to_assign.position;
    charge = to_assign.charge;
    mass = to_assign.mass;
    name = to_assign.name;
    my_particle_kind_iter = to_assign.my_particle_kind_iter;
    return *this;
  }
} t_particle;

struct s_bond
{
  t_particle * particle_1;
  t_particle * particle_2;
  std::vector<t_bond_param>::iterator my_bond_kind_iter;

  s_bond& operator=(const s_bond &to_assign)
  {
    particle_1 = to_assign.particle_1;
    particle_2 = to_assign.particle_2;
    my_bond_kind_iter = to_assign.my_bond_kind_iter;
    return *this;
  }
};

struct s_angle
{
  t_particle * particle_1;
  t_particle * particle_2;
  t_particle * particle_3;
  std::vector<t_angle_param>::iterator my_angle_kind_iter;

  s_angle& operator=(const s_angle &to_assign)
  {
    particle_1 = to_assign.particle_1;
    particle_2 = to_assign.particle_2;
    particle_3 = to_assign.particle_3;
    my_angle_kind_iter = to_assign.my_angle_kind_iter;
    return *this;
  }
};


struct s_dihedral
{
  t_particle * particle_1;
  t_particle * particle_2;
  t_particle * particle_3;
  t_particle * particle_4;
  std::vector<t_dih_param>::iterator my_dih_kind_iter;

  s_dihedral& operator=(const s_dihedral &to_assign)
  {
    particle_1 = to_assign.particle_1;
    particle_2 = to_assign.particle_2;
    particle_3 = to_assign.particle_3;
    particle_4 = to_assign.particle_4;
    my_dih_kind_iter = to_assign.my_dih_kind_iter;
    return *this;
  }
};

struct s_molecule
{
  std::string res_name;
  std::vector<t_particle> my_particles;
  std::vector<t_bond> my_bonds;
  std::vector<t_angle> my_angles;
  std::vector<t_dihedral> my_dihedrals;

  s_molecule& operator=(const s_molecule &to_assign)
  {
    res_name = to_assign.res_name;
    my_particles = to_assign.my_particles;
    my_bonds = to_assign.my_bonds;
    my_angles = to_assign.my_angles;
    my_dihedrals = to_assign.my_dihedrals;
    return *this;
  }
};

struct s_lj_param
{
  double epsilon;
  double sigma;
  std::string atom_kind_name;
};

struct s_bond_param
{
  std::string atom_1;
  std::string atom_2;
  double bond_coeff;
  double default_length;
};

struct s_angle_param
{
  std::string atom_1;
  std::string atom_2; 
  std::string atom_3;
  double angle_coeff;
  double default_angle;
};

struct s_dih_param
{
  std::string atom_1;
  std::string atom_2; 
  std::string atom_3; 
  std::string atom_4;  
  std::vector<double> dih_coeff;
  std::vector<unsigned int> n;
  std::vector<double> delta;
};

struct s_lookup_tab {
  std::string name;
  int code;
};

#endif /*_COMMON_H*/

وهنا مكالمة أقوم بإضافة var من النوع T_molecule (انظر الرأس أعلاه لتعريف T_MOLECULE) إلى مجموعة من الجزيئات.

    void Molecule_Manager_Main::add_molecule(const t_molecule new_molecule)
{
    std::cout << "TYPE :" << new_molecule.res_name << std::endl; 
    std::cout << "3: BOND PARTICLE 1 : "
      << new_molecule.my_bonds[new_molecule.my_bonds.size()-1].particle_1->name
          << std::endl;  
    std::cout << "3: BOND PARTICLE 2 : "
    << new_molecule.my_bonds[new_molecule.my_bonds.size()-1].particle_2->name
          << std::endl; 
    std::cout << "3: BOND ITER CONST : "
    << new_molecule.my_bonds[new_molecule.my_bonds.size()-1].my_bond_kind_iter->bond_coeff
          << " "
    << new_molecule.my_bonds[new_molecule.my_bonds.size()-1].my_bond_kind_iter->default_length
          << std::endl;
    my_molecules.push_back(new_molecule);
    std::cout << "99: INDEX : " << my_molecules.size()-1 << std::endl;
    std::cout << "TYPE :" << my_molecules[my_molecules.size()-1].res_name << std::endl; 
    std::cout << "4: BOND PARTICLE 1 : "
          << my_molecules[my_molecules.size()-1].my_bonds[my_molecules[my_molecules.size()-1].my_bonds.size()-1].particle_1->name
          << std::endl;  
    std::cout << "4: BOND PARTICLE 2 : "
    << my_molecules[my_molecules.size()-1].my_bonds[my_molecules[my_molecules.size()-1].my_bonds.size()-1].particle_2->name
          << std::endl; 
    std::cout << "4: BOND ITER CONST : "
    << my_molecules[my_molecules.size()-1].my_bonds[my_molecules[my_molecules.size()-1].my_bonds.size()-1].my_bond_kind_iter->bond_coeff
          << " "
    << my_molecules[my_molecules.size()-1].my_bonds[my_molecules[my_molecules.size()-1].my_bonds.size()-1].my_bond_kind_iter->default_length
          << std::endl;
  add_performed = true;
}

هذا يعمل بشكل مثالي ... تُطبع سلسلة Resname ، والمعلومات الموجودة على السندات الأخيرة في مطبوعات Bonds Vector. ثم بمجرد إضافة جميع جزيئات بلدي. أسمي هذا:

t_molecule * Molecule_Manager_Main::get_molecule(unsigned int index)
{
    std::cout << "TYPE :" << my_molecules[index].res_name << std::endl; 
    std::cout << "5: BOND PARTICLE 1 : "
      << my_molecules[index].my_bonds[my_molecules[index].my_bonds.size()-1].particle_1->name
          << std::endl;  
    std::cout << "5: BOND PARTICLE 2 : "
    << my_molecules[index].my_bonds[my_molecules[index].my_bonds.size()-1].particle_2->name
          << std::endl; 
    std::cout << "5: BOND ITER CONST : "
    << my_molecules[index].my_bonds[my_molecules[index].my_bonds.size()-1].my_bond_kind_iter->bond_coeff
          << " "
    << my_molecules[index].my_bonds[my_molecules[index].my_bonds.size()-1].my_bond_kind_iter->default_length
          << std::endl;
  return &(my_molecules[index]);
} 

هذا segfaults على خط السندات.

أستطيع أن أقول من المؤشرات التي أطبقتها في خطوة الإضافة التي لا أقوم بها في الكتابة على الجزيئات التي أدفعها إلى المتجه (الحجم ينمو) ..

بمعنى آخر ، ما يبدو أنه يحدث: اقرأ Sub-Vector (Works)-> إضافة المزيد من العناصر في المتجه الأصل-> إعادة قراءة المستنقع الفرعي (SEG-Faults)

هذه الوظائف هي الوسيلة الوحيدة للاضطراب الجزيئات التي يتعين إضافتها إلى المتجه ، ويتم إضافة جزيئات VARS مرة واحدة فقط ولم يتم تعديلها بعد وفاتها في الاختبار الحالي.

أيه أفكار؟؟؟؟ شكرا لكم مقدما!!

هل كانت مفيدة؟

المحلول

مجرد قراءة يمكنك الوصول إلى araible تسمى my_bond_kind_iter. بعد إضافة المزيد من العناصر في ناقل الأصل ، سيتم تغيير حجمها. هذا يعني (على افتراض أنه ليس لديك حاويات C ++ 0x RVALUE-LATE) بأنه سيتم أيضًا نسخ متجه الطفل ، مما يؤدي إلى إبطال جميع المؤشرات والمراجع الموجودة فيه. لذلك عندما تحاول الوصول إلى هذا التكرار القديم الذي أصبح الآن غير صالح تمامًا ، Hello Scructionation خطأ. سيحدث هذا بالطبع أيضًا إذا قمت بإضافة المزيد إلى متجه الطفل.

تكرارات المتجهات ليست آمنة ، ولا يمكنك الاحتفاظ بها والوصول إليها لاحقًا ، لأن المتجهات تغيير حجمها مما يعني تحريك الذاكرة ، وهذا يحدث في نزوة التنفيذ.

نصائح أخرى

في الكائنات المختلفة ، تقوم بتخزين المتكررين للوصول إلى العناصر في بعض المتجهات. يتم إبطال هؤلاء المتكررين عند تعديل المتجه الأساسي ، على سبيل المثال عن طريق إضافة عناصر جديدة. إلغاء تحديد مثل هذا التكرار هو سلوك غير محدد.

من المحتمل أن تقوم بتعديل المتجهات التي قمت بتخزين التكرار من أجلها عند إضافة جزيئات جديدة واستخدام هذه التكرار في وقت لاحق يؤدي إلى أخطاء التجزئة.

سأكون أنت ، أود أن أعيد هذا الرمز بشدة.

في معظم الأوقات عندما أواجه مشكلة مثلك (وأصبحت نادرة جدًا) ، أعيد تشغيل الكود حتى أرى المشكلة بوضوح. هنا ، هناك الكثير من التكرارات التي يمكن تجنبها بوضوح. استخدم typedefs ، المراجع ، consts لتجنب التكرار.

تتيح لك إعادة التهيئة إعادة تنظيم الكود الخاص بك وفكرك ، والتبسيط ، وجعل المشاكل واضحة. خذ وقتًا للقيام بذلك وستجد مصدر المشكلة.

قد يكون ذلك خارج هذا الرمز.

(حول إعادة البناء ، أوصي بقراءة هذا: http://sourceming.com/refactoring )

سأوصي بتجنب المشغل الفردي (ص.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top