将指针从一个C ++程序传递到另一个链接C ++程序的正确方法是什么?
我有一个C ++程序,它在另一个使用头文件包含的C ++程序中调用名为SaveGatheredVec()的函数。 SaveGatheredVec()将返回一个指向数组的指针,我可以从我调用的函数中打印该数组。但是,当我执行类似下面的操作时,指针没有获得正确的数组地址,只打印出Segmentation Fault。
由于该代码很少且有很多事情正在进行中,只需查看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 increament=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[increament]= j + roffset + 1; increament++;
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 ++函数中定义的函数。感谢。
答案 0 :(得分:3)
“不同程序”究竟是什么意思?你的意思是不同的.cpp文件?在那种情况下,这将是一个不同的翻译单元,它对指针没有任何影响 - 也就是说,你可能在其他地方有一个错误。
如果您在不同的过程中使用不同的程序,则在用户模式下无法实现。每个进程都有自己的virtual address space,专门设计并在硬件和操作系统中实现,以便进程无法访问彼此的内存。
注意:这在内核模式驱动程序中是可能的,其中所有驱动程序共享相同的虚拟地址空间。
您应该发布更多代码,因为很难看到您在fun
中实际执行的操作,以及返回指针指向的数据结构。但是,我冒昧地猜测你正在创建一个本地数组 - 也就是说,在堆栈中 - 并返回指向它的指针。堆栈变量一旦超出范围就会被销毁,这可以解释为什么在函数返回后指针变为无效。
<强>更新强>
在SaveGatheredVec
函数的static int NodesVisited[1];
行中,static
完全不同。没有它,NodesVisited
将在堆栈中,一旦堆栈在函数返回时展开,指向它的指针就会失效。请参阅The stack and the heap和此SO question。
但是,因为你使用了static
,它一直存在到程序结束之前,没有任何东西可以立即显现出来。尝试在NodesVisited
中打印p
,指针和BFS
的值,并检查它们是否相同。另外,请检查totnnz
中的SaveGatheredVec
和cnnz
中的BFS
是否具有相同的值 - 在您的示例中,它们都应为1
。如果cnnz
较大,那么您将读出界限并导致seg错误。
NodesVisited[increament]= j + roffset + 1; increament++;
在您的示例中, increament
[sic:increment]绝不应高于0
。
答案 1 :(得分:0)
正如@Ramon所说,你应该添加更多关于fun()函数的代码。要正确使用int *指针,首先必须对其进行初始化,然后创建一个指向它的内存空间,以复制所需数组的元素。