【问题标题】:Array of pointer correct only if printed?指针数组只有在打印时才正确?
【发布时间】:2016-03-26 15:28:15
【问题描述】:

该函数用于将文本拆分为不同的(可能是平衡的)块(我已经详细讨论过here)。下面是代码(看下面的问题描述):

pair<off_t,off_t>* getSplits() {
    struct stat st;
    off_t size;
    if (stat(file_name.c_str(), &st) == 0)
        size = st.st_size;
    int nMappers = size > nWorkers ? nWorkers : size; //if workers are greater than file size
    pair<off_t,off_t> splits [nMappers];
    double split_size = (double) size / nMappers;
    off_t acc = 0 ;
    ff::ParallelFor pf( ff_realNumCores() );

    string prova = file_name;
    pf.parallel_for(0,nMappers,[&splits,split_size, prova, size](const long i) {
        ifstream ifs (prova , ifstream::in);
        off_t begin = ceil((double) i*split_size);
        off_t end = ceil((double) (i+1)*split_size-1);
        char c;
        string s;
        if(begin>0){
            //if char before the first one is different from ' ' or '\n'
            //then the split begins in the middle of a word (bad)
            ifs.seekg(begin-1,ios::beg);
            ifs.get(c);
            if(c!=' ' && c!='\n'){
                getline(ifs,s,' ');
                begin+=s.length();
            }
            if(begin>end)
                end=begin;
        }
        ifs.seekg(end,ios::beg);
        ifs.get(c);
        if(c!=' ' && c!='\n' && end != size){
            getline(ifs,s,' ');
            end+=s.length();
        }
        splits[i] = {begin, end};
    });
    pair<off_t,off_t> *p = splits;
    for(int i=0;i<nWorkers;i++){
        cout<<"begin="<<p[i].first<<" end="<<splits[i].second<<endl;
    }
    return p;
}

这就是我调用它并打印其内容的方式:

pair<off_t,off_t> *splits = input_format->getSplits();
for(int i=0; i<nWorkers; i++){
    cout<<"outside split begin="<<splits[i].first<<" second="<<splits[i].second<<endl;
    this->ff_send_out(new MapTask<MIK,MIV,MOK,MOV> (record_reader->clone(),splits[i],map_func));
}

问题是如果我在getSplits()内打印p的内容(最后一个for循环),那么结果是正确的:

begin=0 end=13
begin=14 end=14
begin=15 end=21
begin=22 end=28
outside split begin=0 second=13
outside split begin=14 second=14
outside split begin=15 second=21
outside split begin=22 second=28

BUT如果我不这样做(所以我删除了打印for),那么结果是错误的(只有第一对是正确的)!

outside split begin=0 second=13
outside split begin=140152066182136 second=140152054622976
outside split begin=140152066227112 second=29521758
outside split begin=140152054622960 second=2564825869

这怎么可能?

【问题讨论】:

  • 你返回一个悬空指针,未定义的行为。
  • 顺便说一句,您使用 VLA 这是一个扩展。
  • 正如其他人所指出的,您正在返回一个悬空指针,请尝试阅读此内容以获得更多理解stackoverflow.com/questions/1475635/…

标签: c++


【解决方案1】:

你返回一个局部变量的地址,所以你有悬空指针。

我建议改为返回std::vector&lt;std::pair&lt;off_t, off_t&gt;

【讨论】:

  • 我不想使用vector,因为它空间效率低,而且我已经知道元素的确切数量(因此静态数组是更好的选择)。
  • @justHelloWorld:你的大小在编译时是未知的,所以你不能使用数组(除非你使用最大大小,但在一般情况下你会比vector 释放更多的空间)。此外,可以移动矢量,而复制std::array。一个静态数组禁止你调用该方法两次...
  • 我不确定我是否理解您的回复,但我的意思是,据我所知vector 是空间效率低下的,因为如果它在之前分配的空间被填满时将其空间加倍,而固定大小的数组(如new pair&lt;off_t,off_t&gt; [nWorkers])是节省空间的,因为它分配了所需的(而不是更多)空间。
  • 我了解vector 拥有capacity 成员这一事实...您可以使用reserveshrink_to_fit 管理容量大小。
【解决方案2】:

您将获得一个指向堆栈的指针(这是您的函数定义的拆分位置)。

使用全局/静态变量,或者更好的是,传递指针数组并将其填充到函数中。

【讨论】:

    猜你喜欢
    • 2022-11-13
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-17
    相关资源
    最近更新 更多