使用C从C ++访问公共类内存

时间:2009-03-20 14:16:03

标签: c++ c memory class

向所有人致意。

我目前正在UNIX上编写C,C ++和fortran的多语言程序,不幸的是,当我在编译后尝试执行时遇到“分段错误”。

我已经将问题缩小到我程序的C ++和C部分之间的接口。第一部分包括main.ccp和SA.cpp,以及第二部分CFE.c.

一个名为'SimAnneal'的类在SA.cpp中存在,具有公共向量DensityArray和ElementArray。该计划的顺序如下:

  1. 创建SimAnneal对象'Obj1'并调用函数ObjFunction()

  2. 该函数初始化矢量大小

  3. 使用指向两个向量及其长度的指针调用CFE(...)。

  4. CFE.c通过使用指针直接编辑向量的数据元素

  5. ObjFunction()使用EnergyArray(和可能的DensityArray)数据。

  6. 所有来源的相关脚本如下:

    的main.cpp

    #include "SA.h" 
    
    int main() 
    {   
        SimAnneal Obj1;
    
        Obj1.ObjFunction();
    
        return 0;
    }
    

    SA.h

    class SimAnneal 
    {
        void Initialize ();
        ...
      public
        std::vector<float> DensityArray; 
        std::vector<float> EnergyArray;
        double ObjFunction ();
        ...
    }
    

    SA.cpp

    #include "CFE.h"
    
    void SimAnneal::Initialize ()
    {
        int length = 15;
        EnergyArray.resize(length);
    DensityArray.resize(length);
    }
    
    double SimAnneal::ObjFunction () 
    {
        Initialize ();
    
        CFE(&DensityArray[0], &EnergyArray[0], DensityArray.size()); 
    
          // sends pointers of both arrays to CFE.c, which will then 
          // directly modify the array
    
        double SumStrainEnergy = 0;
    
        for (int i = 0; i < EnergyArray.size(); i++)
        {
            SumStrainEnergy += EnergyArray[i];  //Effectively sum of array 
                                                //engy[] from CFE.c
        }
    
        return SumStrainEnergy;
    }
    

    CFE.h

    #ifdef __cplusplus
    extern "C" {
    #endif 
    
    void CFE(float density[], float energy[], int NumElem);
    
    #ifdef __cplusplus
     }
    #endif
    

    CFE.c

    void CFE(float density[], float energy[], int NumElem)
    {
        ...
    
        float * dens;
        dens = density;  //pass pointer of array density[0] in SA.cpp to CFE.c
    
        for(n=0; n<NumElem; n++)
        { ... modify dens (e.g. DensityArray from SA.cpp) ... }
    
        float * engy;
        engy = energy; //pass pointer of array energy[0] in SA.cpp to CFE.c
    
        for(n=0; n<NumElem; n++)
        { ... modify engy (e.g. EnergyArray from SA.cpp) ... }   
    }
    

    我是否通过尝试从程序的C部分访问向量元素来导致非法内存访问?有没有可靠的方法允许这个?

    任何帮助都会受到很大关注。

5 个答案:

答案 0 :(得分:11)

如果你保持在向量的范围内,你正在做的事情似乎没问题。

你可以通过做你正在做的事情来处理std :: vector,就像它是一个C数组一样 - 取第一个元素的地址。 C ++标准已经更改为专门允许这种用法。

目前无法找到C ++的技术勘误表2003,但显然相关部分参考文献是23.2.4,

答案 1 :(得分:1)

您发布的代码似乎没问题 - 如果您希望调试问题,则需要提供更多详细信息。实际上,如果你在调试器中运行程序,它应该能够准确地告诉你导致异常的代码行(你可能需要查看调用堆栈),或者只是单步调试程序直到它崩溃。 / p>

至于关于vector是否可以被视为C数组的混淆,它肯定可以通过获取第一个元素的地址(即。&vect[0]) - 如果向量包含元素。

C ++ 03标准在23.2.4中说明vector<>

  

向量的元素是连续存储的,这意味着如果vvector<T, Allocator>,其中T是除bool以外的某种类型,那么它就服从&v[n] == &v[0] + n所有0 <= n < v.size()

{1}}

请注意,这在C ++ 98标准中没有明确说明(但仍然是意图)。

另见Herb Sutter的文章:

请注意,vector<bool>不能被视为C数组 - 这是一种特殊情况,因为vector<bool>中的元素未存储为bool

答案 2 :(得分:0)

你做不到。 Vector类与C类数组不同。

在将其传递给CFE函数之前,必须将其转换为常规C数组。

编辑: 显然我的回答是错误的。查看Neil的帖子。

答案 3 :(得分:0)

您发布的代码是正确的。如果对CFE()内部的数组元素的每次访问都在边界内,则不应该出现分段错误。尝试在valgrind下运行您的程序,看看它是否报告任何异常。

答案 4 :(得分:0)

CFE()的内容是什么?

为什么不将CFE()定义为; void CFE(float * density,float * energy,int NumElem);

所以你不必愚弄演员而只是这样做;密度[i] = ...在你的循环里面?