【问题标题】:Array of doubles and heap corruption双精度数组和堆损坏
【发布时间】:2012-05-28 08:22:43
【问题描述】:

我有一个类似的功能

template <class Type>
myFunc(Type** arrayToBeFilled);

我这样称呼它:

double* array = NULL;
myFunc(&array);

在函数内部,我使用 strtod 函数读取和解析数字:

//这里是文件打开,获取每行的行数和双打数

...
    char *inputString = new char[LONG_STRING_SIZE]; 
    char *pNext = NULL;
   (*arrayToBeFilled) = new Type[length*rowSize];

for (int i=0; i<length; i++)
    { 
        source.getline(inputString, LONG_STRING_SIZE);
        pNext = NULL;

     for (int j=0; j<rowSize; j++)
     {
         double d = strtod(inputString, &pNext);
        (*arrayToBeFilled)[i*rowSize+j] = d;
        inputString = pNext;
        pNext = NULL;
     }
    }

变量 d 仅用于调试器检查 - 运行时就可以了。 但是在填充数组后我尝试打印它(只是为了检查)

for (int i=0; i<length; i++)

    {
        for (int j=0; j<rowSize; j++)
            {
                cout<<(*arrayToBeFilled)[i*rowSize+j]<<"  ";
            }
        cout<<"\n";
    } 

这里出现了错误的输出 - 其他数字,有时是堆损坏等等。我在函数内外打印它 - 结果相同。而且我不能删除这个数组 no 或没有函数 - 运行时错误跟随我!

【问题讨论】:

  • 您发布的代码看起来不错 - 问题可能出在您尚未发布的代码中。你能发布一个产生错误的完整示例吗?
  • 不应该是 i*length (因为你正在迭代长度)+ j?
  • @KamilKlimek:不。将i 视为要跳过以到达当前行开头的行数。因此要跳过的元素的数量是i*rowSize
  • 请注意,您使用new char[LONG_STRING_SIZE] 在堆上创建一个原始C 数组,并将指向它的指针分配给inputString;然后你用来自pNext的赋值修改inputString:那么,你泄漏inputString初始数组了吗?
  • @Mr_C64 是的,你是对的!解决了一个问题。

标签: c++ arrays pointers memory-management


【解决方案1】:

为什么在 C++ 中使用原始 C 数组?如果您使用 STL 类,例如 std::vector 而不是原始的 new[],您的代码将变得更简洁、更易于阅读和维护(例如,您不需要显式调用 delete[]:析构函数将清理堆内存)。一般来说,在现代 C++ 中,规则是“如果你写的是 new 或 delete,你就做错了”(有一些例外)。

另请注意,使用 C++11 移动语义,您可以简单地返回 vector 而不是使用输出引用/指针参数:

template <typename Type>
inline std::vector<Type> myFunc()
{
    ...
}

在你的函数体内,而不是你的代码

(*arrayToBeFilled) = new Type[length*rowSize];

只写:

std::vector<Type> arrayToBeFilled(length*rowSize);

然后简单地return arrayToBeFilled;

(还要注意vector 可以嵌套在一起:您也可以使用vector&lt;vector&lt;Type&gt;&gt; 来制作二维数组,但这比单个vector&lt;Type&gt; 效率低,后者更直接映射到您的原始@ 987654332@电话。)

此外,在您发布的代码中,您使用new char[LONG_STRING_SIZE] 在堆上创建了一个原始C 数组,并将指向它的指针分配给inputString;然后你用来自pNext 的赋值修改inputString:但是这样做会泄露指针存储在inputString 中的初始数组。

【讨论】:

  • 100% 正确,但我测试了原始数组和向量的迭代,并且使用最大优化数组要好得多。所以我试着去熟悉他们的表现。
  • 如果您使用的是 Visual C++,您是否比较了 release 构建中的性能(在调试构建中,有额外的机制来检测缓冲区溢出、无效迭代器等,即有助于调试但会导致开销)?
【解决方案2】:

好像你没有返回类型

template <class Type>
void myFunc(Type** arrayToBeFilled);

你应该初始化你的函数

double array = NULL;
myFunc<double>(&array);

在输入时,打印出你得到的值,通常你可能会得到一些意想不到的东西,从而导致错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 2020-10-03
    相关资源
    最近更新 更多