将指针从一个C ++程序传递到另一个链接C ++程序的正确方法是什么?

时间:2017-07-31 02:42:19

标签: c++ arrays pointers

将指针从一个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 ++函数中定义的函数。感谢。

2 个答案:

答案 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中的SaveGatheredVeccnnz中的BFS是否具有相同的值 - 在您的示例中,它们都应为1。如果cnnz较大,那么您将读出界限并导致seg错误。

NodesVisited[increament]= j + roffset + 1; increament++;
在您的示例中,

increament [sic:increment]绝不应高于0

答案 1 :(得分:0)

正如@Ramon所说,你应该添加更多关于fun()函数的代码。要正确使用int *指针,首先必须对其进行初始化,然后创建一个指向它的内存空间,以复制所需数组的元素。