我遇到了一个非常令人沮丧的指针问题。我以前发布在这里: TOUGH: Dealing with deeply nested pointers in C++
但那个帖子过长而且陈旧,所以我选择重新发布更多细节。
这是我的头文件,用于定义我的类型:
#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*/
这是一个调用,我将一个类型为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字符串,并打印bond矢量中最后一个键的信息。然后,一旦我添加了所有的分子。我称之为:
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]);
}
这种债券线上的断裂。
我可以从添加步骤中打印的索引中看出,我没有覆盖我正在推动向量的分子(大小正在增长)..
换句话说,似乎正在发生的事情是: 读子矢量(工作) - &gt;在父矢量中添加更多项目 - &gt;重读子矢量(seg-faults)
这些功能是分子变量添加到载体的唯一手段,分子变量只添加一次,并且在我目前的测试中没有被修改。
任何想法????提前谢谢!!
答案 0 :(得分:1)
只需阅读您访问名为my_bond_kind_iter的变量即可。在父矢量中添加更多项后,它将调整大小。这意味着(假设您没有C ++ 0x rvalue-aware容器)也会复制子向量,使所有现有指针和引用无效。因此,当您尝试访问现在完全无效的旧迭代器时,您好分段错误。如果在子向量中添加更多内容,当然也会发生这种情况。
向量迭代器不安全,你不能保留它们并在以后访问它们,因为向量调整大小意味着移动内存,这种情况发生在实现的时候。
答案 1 :(得分:0)
在不同的对象中,存储迭代器以访问某些向量中的元素。修改基础向量时,这些迭代器会失效,例如通过添加新元素。取消引用这样的迭代器是未定义的行为。
当您添加新分子并稍后使用这些迭代器导致分段错误时,您可能会修改已存储迭代器的向量。
答案 2 :(得分:0)
我会是你,我会严重重构这段代码。
大部分时间我遇到像你这样的问题(并且它变得非常罕见)我重构代码直到我清楚地看到问题。在这里,可以清楚地避免重复过多。使用typedef,references,consts来避免重复。
重构允许您重新组织代码和思想,简化,使问题显而易见。花点时间做这个,你会找到问题的根源。
这可能不在此代码中。
(关于重构,我建议阅读:http://sourcemaking.com/refactoring)
答案 3 :(得分:0)
我建议在编写跟踪代码(但不限制跟踪代码)时避免使用下标运算符(例如ex.my_molecules [index]),而更喜欢()成员函数。