将数组指针从一个 C++ 程序传递到另一个链接的 C++ 程序的正确方法是什么?
我有一个 C++ 程序,它调用另一个使用头文件包含的 C++ 程序中名为 SaveGatheredVec() 的函数。
SaveGatheredVec()
应返回一个指向数组的指针,我可以从我调用的函数中打印该数组。但是当我执行如下操作时,指针没有获取数组的正确地址,只是打印分段错误。
由于代码有点混乱,而且发生了很多事情,只需查看
NodesVisited[]
和指针 p 就是我需要帮助的地方。我什至尝试在 cpp 程序中声明一个全局变量,从我调用 SaveGatheredVec
并将数组传递给函数,但它仍然给出相同的错误。
#include<iostream>
#inlcude "AnotherC++Program.h"
...
main(){
BFS();
}
void BFS(PSpMat<ElementType>::MPI_DCCols D, PSpMat<ElementType>::MPI_DCCols B, int ACol, string output){
int *p=0;
PSpMat<ElementType>::MPI_DCCols C = Mult_AnXBn_DoubleBuff<PTDOUBLEDOUBLE, ElementType, PSpMat<ElementType>::DCCols>(D,B);
int64_t cnnz = C.getnnz();
ostringstream tinfo;
p=C.SaveGatheredVec(output);
for(int i=0; i<cnnz; i++)
cout << "\n-----" << *(p+i);// on return it says Segmentation Fault
}
SaveGatheredVec() 在另一个由标头链接的 C++ 程序中定义,如下所示:
#include<iostream>
...
template <class IT, class NT, class DER>
template <class HANDLER>
int * SpParMat< IT,NT,DER >::SaveGatheredVec( string filename, HANDLER handler, bool transpose) const
{
int proccols = commGrid->GetGridCols();
int procrows = commGrid->GetGridRows();
IT totalm = getnrow();
IT totaln = getncol();
//IT totnnz = getnnz();
IT totnnz = 1;
static int NodesVisited[1]; //for example purpose, this is made just of size 1
int increment=0;
int flinelen = 0;
ofstream out;
if(commGrid->GetRank() == 0)
{
std::string s;
std::stringstream strm;
strm << "%%MatrixMarket matrix coordinate real general" << endl;
strm << totalm << " " << totaln << " " << totnnz << endl;
s = strm.str();
out.open(filename.c_str(),ios_base::trunc);
flinelen = s.length();
out.write(s.c_str(), flinelen);
out.close();
}
int colrank = commGrid->GetRankInProcCol();
int colneighs = commGrid->GetGridRows();
...
for(int j = 0; j < 2; ++j)
{
IT rowcnt = 0;
sort(csr[j].begin(), csr[j].end());
int mysize = csr[j].size();
MPI_Gather(&mysize, 1, MPI_INT, gsizes, 1, MPI_INT, 0, commGrid->GetRowWorld());
if(commGrid->GetRankInProcRow() == 0)
{
rowcnt = std::accumulate(gsizes, gsizes+proccols, static_cast<IT>(0));
std::partial_sum(gsizes, gsizes+proccols-1, dpls+1);
ents = new pair<IT,NT>[rowcnt];
}
MPI_Gatherv(SpHelper::p2a(csr[j]), mysize, datatype, ents, gsizes, dpls, datatype, 0, commGrid->GetRowWorld());
if(commGrid->GetRankInProcRow() == 0)
{
for(int k=0; k< rowcnt; ++k)
{
if (!transpose){
//NodesVisited is assigned below
NodesVisited[increment]= j + roffset + 1; increment++;
out << j + roffset + 1 << "\t" << ents[k].first + 1 << "\t";
handler.save(out, ents[k].second, j + roffset, ents[k].first);}
else
{
out << ents[k].first + 1 << "\t" << j + roffset + 1 << "\t";
handler.save(out, ents[k].second, j + roffset, ents[k].first);
}
out << endl;
}
delete [] ents;
}
}
if(commGrid->GetRankInProcRow() == 0)
{
DeleteAll(gsizes, dpls);
out.close();
}
}
MPI_Barrier(commGrid->GetWorld());
}
for(int j=0; j<totnnz;j++)
cout << "\nHere" << NodesVisited[j]; //values are printed correctly here
return NodesVisited;
}
如果有人可以提供示例或一些想法来帮助我如何从另一个 C++ 中定义的函数中检索数组的值,这将非常有帮助,因为我必须使用另一个 C++ 函数中定义的函数。谢谢。
“不同的程序”到底是什么意思?您是指不同的 .cpp 文件吗?在这种情况下,这将是一个不同的翻译单元,并且它对于指针实际上没有任何影响 - 也就是说,您可能在其他地方遇到错误。
如果您指的是不同进程中的不同程序,那么这在用户模式下是不可能的。每个进程都有自己的虚拟地址空间,在硬件和操作系统中专门设计和实现,以便进程不能访问彼此的内存。
注意:这在内核模式驱动程序中是可能的,其中所有驱动程序共享相同的虚拟地址空间。
您应该发布更多代码,因为很难看出您在
fun
中实际做了什么,以及您的返回指针指向什么数据结构。但是,我大胆猜测您正在创建一个本地数组(即在堆栈中)并返回指向该数组的指针。堆栈变量一旦超出范围就会被销毁,这可以解释为什么一旦函数返回你的指针就会变得无效。
更新
在您的
SaveGatheredVec
函数中,在 static int NodesVisited[1];
行中,static
使一切变得不同。如果没有它,NodesVisited
将位于堆栈中,并且一旦堆栈在函数返回时展开,指向它的指针就会失效。请参阅堆栈和堆以及这个SO问题。
但是,因为您使用了
static
,所以它会一直存在到程序结束,并且没有任何立即明显的东西。尝试打印指针 NodesVisited
的值以及 p
中 BFS
的值,并检查它们是否相同。另外,检查 totnnz
中的 SaveGatheredVec
和 cnnz
中的 BFS
是否具有相同的值 - 在您的示例中它们都应该是 1
。如果 cnnz
较大,那么您将读取越界并导致段错误。
NodesVisited[increment]= j + roffset + 1; increment++;
在您的示例中,increment
永远不应高于 0
。
正如@Ramon 所说,你应该放置更多关于 fun() 函数的代码。要正确使用 int* 指针,首先必须初始化它,然后在它指向的位置创建一个内存空间,以复制所需的数组元素。