C ++中的古怪的指针问题 [英] Weird Pointer issue in C++

查看:224
本文介绍了C ++中的古怪的指针问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个非常令人沮丧的指针问题。我以前在这里发布:
http://stackoverflow.com / questions / 3114997 / 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

模板< 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 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_particles * 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>三角洲;
};

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

#endif / * _ COMMON_H * /

我要添加一个类型为t_molecule的var(见上面的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字符串打印,最后一个债券在债券矢量打印。然后一旦我添加了我所有的分子。我称之为:

  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在债券线。



我可以从添加步骤中打印的索引中看出,我不会覆盖我正在向量上的分子(大小越来越大)。



换句话说,发生的事情是:
读取子向量(工作) - >在父向量中添加一些项 - vector(seg-faults)



这些函数是分子变量加入向量的唯一方法,分子变量只添加一次,而不是在我的目前的测试。



任何想法?提前感谢!

解决方案

只是读取你访问一个可变的名为my_bond_kind_iter。在父矢量中添加更多项目后,它将调整大小。这意味着(假设你没有C ++ 0x右值感知容器)子向量也将被复制,使所有存在的指针和引用无效。所以当你尝试访问这个旧的迭代器,现在完全无效,hello分段故障。这当然也会发生,如果你添加更多的子向量。



向量迭代器是不安全的,你不能保留它们,以后访问它们,因为向量调整大小,这意味着移动内存,这发生在实现的whim。 / p>

I'm running into a VERY frustrating pointer issue. I previously posted here: http://stackoverflow.com/questions/3114997/tough-dealing-with-deeply-nested-pointers-in-c

But that post got overly long and is stale, so I chose to repost with more details.

Here is my header file that defines my types:

#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*/

And here is a call that I make to add a var of type t_molecule (see above header for t_molecule's definition) to an array of molecules.

    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;
}

This works perfectly... the resname string prints, and the info on the last bond in the bonds vector prints. Then once I've added all my molecules. I call this:

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]);
} 

This segfaults on the bonds line.

I can tell from the indices I print in the add step that I'm not overwriting the molecules I'm pushing onto the vector (the size is growing)..

In other words what appears to be happening is: Read sub-vector (works) -> add some more items in parent vector -> reread sub-vector (seg-faults)

These functions are the ONLY means for molecules vars to be added to the vector, and molecules vars are only added once and not modified posthumously in my current test.

Any ideas???? Thank you in advance!!

解决方案

Just reading that you access a varaible called my_bond_kind_iter. After you add some more items in the parent vector, it will resize. This means (assuming that you don't have C++0x rvalue-aware containers) that the child vector will also be copied, invalidating all existing pointers and references into it. So when you try to access this old iterator that is now thoroughly invalid, hello segmentation fault. This will of course also happen if you add more into the child vector.

Vector iterators are not safe, you cannot keep them around and access them later, because vectors resize which means moving memory, and this happens at the whim of the implementation.

这篇关于C ++中的古怪的指针问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆