C ++ malloc / realloc奇怪的行为

时间:2018-05-11 19:05:59

标签: c++ memory malloc realloc

我正在编写一个动态数组供我自己使用,我想用0预设。

template <class T>
dynArr<T>::dynArr()
{
rawData = malloc(sizeof(T) * 20); //we allocate space for 20 elems
memset(this->rawData, 0, sizeof(T) * 20); //we zero it!
currentSize = 20;
dataPtr = static_cast<T*>(rawData); //we cast pointer to required datatype.
}

这部分工作 - 通过循环迭代与dereferencind迭代dataPtr工作得很好。零。

然而,重新分配行为(在我看来)至少有点奇怪。首先,您必须查看重新分配代码:

template <class T>
void dynArr<T>::insert(const int index, const T& data)
{

    if (index < currentSize - 1)
    {
        dataPtr[index] = data; //we can just insert things, array is zero-d
    }

    else
    {
        //TODO we should increase size exponentially, not just to the element we want

        const size_t lastSize = currentSize; //store current size (before realloc). this is count not bytes.

        rawData = realloc(rawData, index + 1); //rawData points now to new location in the memory
        dataPtr = (T*)rawData;
        memset(dataPtr + lastSize - 1, 0, sizeof(T) * index - lastSize - 1); //we zero from ptr+last size to index

        dataPtr[index] = data;
        currentSize = index + 1;
    }

}

简单,我们将数据重新分配到索引+ 1,并将尚未归零的内存设置为0。

对于测试,我首先在该阵列的第5位插入5。预期的事情发生了 - 0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

然而,插入其他东西,比如插入(30,30)会给我带来奇怪的行为:

0, 0, 0, 0, 0, 5, 0, -50331648, 16645629, 0, 523809160, 57600, 50928864, 50922840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,

到底是什么,我在这里不明白吗?不应该realloc考虑所有20个先前设置的内存字节?这里有什么巫术。

1 个答案:

答案 0 :(得分:4)

问题1:

您在realloc的通话中使用了错误的尺寸。将其更改为:

rawData = realloc(rawData, sizeof(T)*(index + 1)); 

如果rawData的类型为T*,则为

rawData = realloc(rawData, sizeof(*rawData)*(index + 1)); 

问题2:

以下的最后一个词是不对的。

memset(dataPtr + lastSize - 1, 0, sizeof(T) * index - lastSize - 1); 

您需要使用:

memset(dataPtr + lastSize - 1, 0, sizeof(T) * (index - lastSize - 1));
                               //  ^^              ^^
                               // size      *  The number of objects 

问题3:

使用

分配给dataPtr
dataPtr[index] = data;
使用mallocrealloc获取内存时,

是一个问题。 malloc函数族只返回原始内存。它们不初始化对象。 分配给未初始化的对象是所有非POD类型的问题。

问题4:

如果T是具有虚拟成员函数的类型,则使用memset将内存清零将极有可能导致问题。

解决所有问题的建议:

使用newdelete会更好,因为你在C ++的土地上。

template <class T>
dynArr<T>::dynArr()
{
   currentSize = 20;
   dataPtr = new T[currentSize];
   // Not sure why you need rawData
}

template <class T>
void dynArr<T>::insert(const int index, const T& data)
{
   if (index < currentSize - 1)
   {
      dataPtr[index] = data;
   }

   else
   {
      const size_t lastSize = currentSize;
      T* newData = new T[index+1];
      std::copy(dataPtr, dataPtr+lastSize, newData);
      delete [] dataPtr;
      dataPtr = newData;
      dataPtr[index] = data;
      currentSize = index + 1;
   }
}

请注意,仅当T是默认构造时,建议的更改才有效。

这也将解决上述问题3和4。