使用C从C ++访问公共类内存
问候每个人。
我目前正在UNIX上编写C,C ++和fortran的多语言程序,不幸的是,当我在编译后尝试执行时遇到“分段错误”。
我已经将问题缩小到我程序的C ++和C部分之间的接口。 第一部分包括main.ccp和SA.cpp,以及第二部分CFE.c.
一个名为’SimAnneal’的类在SA.cpp中存在,具有公共向量DensityArray和ElementArray。 该计划的顺序如下:
-
创建SimAnneal对象’Obj1’并调用函数ObjFunction()
-
该函数初始化矢量大小
-
使用指向两个向量及其长度的指针调用CFE(…)。
-
CFE.c通过使用指针直接编辑向量的数据元素
-
ObjFunction()使用EnergyArray(和可能的DensityArray)数据。
所有来源的相关脚本如下:
main.cpp中
#include "SA.h" int main() { SimAnneal Obj1; Obj1.ObjFunction(); return 0; }
SA.h
class SimAnneal { void Initialize (); ... public std::vector DensityArray; std::vector 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 (eg 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 (eg EnergyArray from SA.cpp) ... } }
我是否通过尝试从程序的C部分访问向量元素来导致非法的内存访问? 有没有确定的方法允许这个?
任何帮助都会很有帮助。
如果你保持在向量的范围内,你正在做的事情似乎没问题。
通过执行您正在执行的操作,您可以将std :: vector完全视为C数组 – 获取第一个元素的地址。 C ++标准已经更改为专门允许这种用法。
目前无法找到C ++的技术勘误表副本2003,但显然相关部分参考文献是23.2.4,
您发布的代码似乎没问题 – 如果您希望调试问题,则需要提供更多详细信息。 实际上,如果你在调试器中运行程序,它应该能够准确地告诉你导致exception的代码行(你可能必须查看调用堆栈),或者只是单步执行程序直到它崩溃。
至于关于vector是否可以被视为C数组的混淆,它肯定可以通过获取第一个元素的地址(即。, &vect[0]
) – 如果向量包含元素。
C ++ 03标准在23.2.4中说明了vector<>
:
向量的元素是连续存储的,这意味着如果
v
是vector
,其中T
是除bool
之外的某种类型,则它遵循所有0 <= n < v.size()
的标识&v[n] == &v[0] + n
0 <= n < v.size()
请注意,这在C ++ 98标准中没有明确说明(但仍然是意图)。
另见Herb Sutter的文章:
请注意, vector
不能被视为C数组 - 这是一种特殊情况,因为vector
中的元素不会存储为bool
。
你不能这样做。 Vector类与C类数组不同。
在将其传递给CFE函数之前,必须将其转换为常规C数组。
编辑:显然我的回答是错误的。 查看Neil的post。
您发布的代码是正确的。 如果对CFE()
内部的数组元素的每次访问都在边界内,则不应该出现分段错误。 尝试在valgrind下运行您的程序,看看它是否报告任何exception。
CFE()的内容是什么?
为什么不将CFE()定义为; void CFE(float * density,float * energy,int NumElem);
所以你不必愚弄演员,只是这样做; 密度[i] = …在你的循环内?