【问题标题】:How do I delete this Void Pointer?如何删除此无效指针?
【发布时间】:2011-08-21 13:12:37
【问题描述】:
#define ALIGNBUF(Length) Length % ALIGNSIZE ? \
              Length + ALIGNSIZE - (Length % ALIGNSIZE) : Length 

short NumCols;
long * ColLenArray, * OffsetArray;

ColLenArray = new long(NumCols * sizeof(long));
OffsetArray = new long(NumCols * sizeof(long));

// THIS CODE SHOULD NOT BE NEEDED TO UNDERSTAND THE PROBLEM
// BUT I HAVE INCLUDED IT JUST IN CASE
////////////////////////////////////////////////////////////
SQLColAttribute(hstmt, ((SQLUSMALLINT) i)+1, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, &ColLenArray[i]);
    ColLenArray[i] = ALIGNBUF(ColLenArray[i]);
    if (i)
        OffsetArray[i] = OffsetArray[i-1]+ColLenArray[i-1]+ALIGNBUF(sizeof(SQLINTEGER));
////////////////////////////////////////////////////////////

void **DataPtr = new void*[OffsetArray[NumCols - 1] + ColLenArray[NumCols - 1] + ALIGNBUF(sizeof(long))];

delete []DataPtr;

觉得做不到,能想到的办法都试过了。

此代码有效,因为在程序运行时,我无法释放内存。每次调用此代码时(并非所有代码都包括在内,因为它不相关)内存变大。我认为删除不正确,void * 一直在增长。

我还根据这里的建议更改了上面的一些代码,但是由于这段代码,内存一直在增长。

【问题讨论】:

  • ColLenArray = new long(NumCols * sizeof(long)); 这是一个错字吗?你稍后再做ColLenArray[NumCols - 1]
  • @Luc 我没发现问题? ColLenArray 是一个指针。
  • 一个指针是的,但指向一个 long。您只能在指向数组元素的指针中建立索引。
  • @Luc 我也在创建指针后调用了这段代码。 SQLColAttribute(hstmt, ((SQLUSMALLINT) i)+1, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, &ColLenArray[i]); ColLenArray[i] = ALIGNBUF(ColLenArray[i]);
  • @PoiXen &ColLenArray[i] 是一个右值,您不能通过它修改 ColLenArray 并且 ColLenArray[i] = ALIGNBUF(...); 分配仍然不会修改 ColLenArray 索引它。无论您以哪种方式对其进行切片,每次都会索引指向单个 long 的指针,因此我希望 i(和其他偏移量)始终为 0...这也适用于 OffsetArray

标签: c++ memory-management void-pointers


【解决方案1】:

您不能在 void * 上调用 delete

解决方案是不要将指向void** 的指针(这是new void*[...] 将提供给您的)到void*。我真的不知道您的代码应该做什么,但是您是否尝试过将DataPtr 的类型更改为void **

更一般地说,在 C++ 中尽可能避免使用void* 有更好的解决方案。如果您编辑您的问题以描述您想要实现的目标,那么我们也许可以提供一些建议。

【讨论】:

  • @user:你应该可以在void ** 上调用delete(或delete [])。
  • @Oli:聪明的措辞“避免无效”:D +1
【解决方案2】:

您应该尽量避免混淆void*new。实际上,在 C++ 中,new 旨在自动确定指针的类型;那为什么不应该使用它。如果您只是处理原始字节,至少可以使用char*

另外一点是new void*[SIZE]分配void**。所以你应该把声明改成void **DataPtr。删除new 之前的类型转换。你现在可以delete[] DataPtr;

编辑:

代码有问题,变量声明如下:

ColLenArray = new long[NumCols * sizeof(long)]; // declare as long[] (not long())
OffsetArray = new long[NumCols * sizeof(long)];

当您将这些变量声明为 new long();它将简单地初始化值并分配一个指向 single long 的指针。

发生内存损坏是因为您使用了ColLenArray[i],它访问了错误的内存。由于您要将上述变量用作数组,因此它应该是new long[]。这样就不会发生内存损坏。使用后,您应该delete[]他们。

【讨论】:

  • @iammilind 改变 void DataPtr = (void)new void**[OffsetArray[NumCols - 1] + ColLenArray[NumCols - 1] + ALIGNBUF(sizeof(SQLINTEGER)) ];到 void **DataPtr = new void*[OffsetArray[NumCols - 1] + ColLenArray[NumCols - 1] + ALIGNBUF(sizeof(SQLINTEGER))];似乎没有释放内存,在任务管理器中检查,内存随着每个函数调用不断增加。
  • 我在回答中建议了void** DataPtr = new void*[...];。你试过吗?同样在解除分配时,它应该是delete[] DataPtr;,因为您正在分配数组。
【解决方案3】:

您只是想要一块可以传递给某些数据库库例程的内存块?这样分配:

char * buffer = new char[ len ];

len 是以字节为单位的缓冲区长度。要删除,只需执行以下操作:

delete [] buffer;

您希望将 void* 传递给函数吗?

void * DataPtr = static_cast< void* >( buffer );

对于额外的优点点,使用提升来管理删除:

boost::scoped_array< char > buffer( new char[ len ] );

...那么您不必担心删除。要在此处获取缓冲区,您需要:

void * DataPtr = static_cast< void* >( buffer.get() );

【讨论】:

    猜你喜欢
    • 2014-08-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2012-07-23
    • 2016-02-22
    • 2014-09-06
    • 1970-01-01
    相关资源
    最近更新 更多