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

问题描述 投票:0回答:2

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

c++ arrays pointers
2个回答
3
投票

“不同的程序”到底是什么意思?您是指不同的 .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


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.