读取新的填充数组会产生段错误

时间:2011-12-07 07:26:25

标签: c++

我一直在努力争取这个......我在main()中创建了一个指针,我将其传递给另一个函数。在该函数内部,指针用于创建新数组(使用new运算符),数组已填充,函数结束。

如果我然后尝试访问调用者中新数组中的元素,我会得到一个段错误。由于使用了new运算符,我希望新数组在堆上,因此不会因为它超出范围而被清除......我真的不明白。我在俯瞰什么?我也不知道谷歌的确切内容,所以还没有运气。

如果我让函数返回指针(而不是传递它),我可以让它工作,但我不想这样做,因为最终我希望我的函数创建一些这样新创建的数组。那我在这里错过了什么?

这是一个最小的工作示例:

#include <iostream>
#include <stdio.h>

bool getData(double *myData)
{
    myData = new double[2];
    if (!myData)
        return false;

    myData[0] = +4.53;
    myData[1] = -3.25;    
    return true;
}


int main()
{
    double *myData = NULL;
    if (!getData(myData))
        fprintf(stderr, "Could not get data.\n");

    std::cout << myData[0] << std::endl;
    std::cout << myData[1] << std::endl;

    delete [] myData;    
}

5 个答案:

答案 0 :(得分:3)

崩溃的根本原因:
当您通过值传递指向函数的指针时。指针的副本将传递给函数。此外,您将内存分配给通过main传递的指针副本,此指针与您在main中访问的指针不同,它是一个副本。 main中的指针myData从未分配任何内存,因此最终您取消引用NULL指针,导致未定义行为并发生崩溃。

建议的解决方案1:

通过参考:

传递指针
bool getData(double *&myData)
                     ^

你很高兴。这是C ++的做法。

另一种解决方案:

你也可以这样做:

bool getData(double **myData) 
                    ^
{
     *myData = new double[2];
      //so on
}

将其称为:

getData(&myData); 
        ^

提醒:
如果未能分配内存,new不会返回NULL。它会引发std::bad_alloc异常。因此,您需要处理该异常,或者如果您想要检查null,则应使用nothrownew

答案 1 :(得分:1)

getData()的指针参数是按值传递的,而不是通过引用传递的。这意味着您正在推送堆栈上的值(==指针指向的地址)并调用getData。在getData中,你用new []的返回值覆盖这个值。从函数返回后该值不再有效,因为它只存在于堆栈中。

尝试将引用或指针传递给指针:

bool getData(double *&myData)
{
    myData = new double[2];
    if (!myData)
        return false;

    myData[0] = +4.53;
    myData[1] = -3.25;    
    return true;
}

答案 2 :(得分:0)

你必须传递一个双**作为myData,才能正确初始化你的数组。目前,您的getData函数创建一个数组并将其值存储在复制的参数中,因此不修改main中的myData。您必须传递myData的指针并使用

进行修改
bool getData(double** myData)
{
    *pmyData = new double[2];
    ...
}

并在main中调用getData:

getData(&myData);

答案 3 :(得分:0)

作为myData函数的参数给出的getData作为副本在堆栈上传递。在getData函数中修改该值时,实际上会修改堆栈中的值。

当你返回主函数时,一切都和以前一样(除了内存泄漏)。

最快的解决方案是更改getData函数,如下所示:

bool getData(double *&myData)

你已经完成了。

答案 4 :(得分:0)

您可以通过值将指针传递给函数,而不是引用。试试这个:

bool getData(double* &myData)
{
    ...
}

不同之处在于myData现在是main中指针的引用,而不是函数退出时被销毁的副本。