释放分配给void指针数组的内存

3

我正在声明一个void指针数组,每个指针都指向任意类型的值。
void **values; // 指向任意类型值的void指针数组

以下是初始化values的方法:


    values = (void**)calloc(3,sizeof(void*));
    //can initialize values as: values = new void* [3];
    int ival = 1;
    float fval = 2.0;
    char* str = "word";
    values[0] = (void*)new int(ival);
    values[1] = (void*)new float(fval);
    values[2] = (void*)str;

    //Trying to Clear the memory allocated
    free(*values); 
    //Error: *** glibc detected *** simpleSQL: free(): invalid pointer: 0x080611b4
    //Core dumped
    delete[] values*;
    //warning: deleting 'void*' is undefined
    //Similar Error.

现在,我该如何释放/删除为值(即void指针数组)分配的内存?

你可能的意思是:values = (void**)calloc(3,sizeof(void*)); - botismarius
7个回答

7
我怀疑问题出在你分配values的方式上:values = (void*)calloc(3,sizeof(void))。这应该是sizeof(void *)而不仅仅是sizeof(void)sizeof(void) 可能是零或其他没有任何意义的值,因此一开始您实际上没有分配任何内存...只是愚蠢的幸运使得赋值起作用,当您尝试释放内存时,错误就会弹出。
编辑:你还需要注意C++风格的new/delete和C风格的malloc/free之间的混用会带来麻烦。只要不deletemalloc的东西或者freenew的东西,同时使用两种方式是可以的,但如果你像这样混用它们,你可能会弄混。

好的,对于 void * 和 void 的区别你抓得很好。我没有注意到。 - Jon
谢谢!sizeof(void) 真的让我警觉起来 :-) - Dan Lenski

6

您有三个动态分配的东西需要以两种不同的方式释放:

delete reinterpret_cast<int*>( values[0]);    
delete reinterpret_cast<float*>( values[1]);

free( values); // I'm not sure why this would have failed in your example, 
               //    but it would have leaked the 2 items that you allocated 
               //    with new

请注意,由于str并非动态分配的,因此不应(实际上也不能)被释放。
几点说明:
  • 我假设 sizeof(void) 的意思是 sizeof(void*),因为你所写的代码无法编译
  • 关于您似乎随意进行的转换,我不会多说什么,只能说这种代码是一定会出问题的

我必须同意Mike关于“灾难”的看法。针对OP:你是想用C还是C++编程?在C中,将类型转换为void*通常是有意义的,但你必须知道自己在做什么。在C++中,有其他的习惯用语可以实现你似乎要做的事情。决定你想用哪种语言进行编程 :) - Dan Lenski
我不知道如何在C++中创建包含不同数据类型数据的容器,尝试使用向量,但是它只能包含相同类型的数据。有人能提供其他方法吗? - user27221
有许多不同的方法可以为异构类型创建容器。请参阅此FAQ,了解在C++中执行此操作的几种方法:http://www.parashift.com/c++-faq-lite/containers.html#faq-34.4 - Dan Lenski
我不知道如何在C ++中创建一个包含不同数据类型的容器,这可能是一个很好的SO问题。我认为可能会有一些有趣的答案超越(或至少更详细地涉及)C ++ FAQ答案。 - Michael Burr
我最喜欢的答案是“使用动态语言(如Perl、Python、Ruby)而不是C或C++”。说真的,当你创建了一个良好的基础设施来管理内存和自省任意类型的数组时,你几乎已经重新创造了其中一种语言。 :) - Dan Lenski
请听从Martin York的建议,不要继续走下去。 - Matt Cruikshank

4
这是使用boost::any类的完美场景。此外,您可能希望考虑使用vector而不是分配自己的内存。
std::vector<boost::any>   data;
boost::any i1 = 1; // add integer
data.push_back(i1);

boost::any f1 = 1.0; // add double
data.push_back(f1);

data.push_back("PLOP"); // add a char *

std:: cout << boost::any_cast<int>(data[0]) + boost::any_cast<double>(data[1])
           << std::endl;

回到您的原始代码,主要问题是:
values = (void*)calloc(3,sizeof(void));

// This should  have been
void** values = (void**)calloc(3,sizeof(void*));

// Freeing the members needs care as you need to cast them
// back to the correct type before you release the memory.

// now you can free the array with
free(values);

请注意:尽管在同一段代码中同时使用new/delete和calloc/free不是违法的,但这种做法并不受欢迎。主要原因是很容易混淆,可能会导致致命后果。


现在这真是太棒了。我看到了很多关于Boost的好东西,这可能会让我重新开始学习C++。 - Dan Lenski

1

你正在混合使用new和*alloc()。这是不可取的,可能会导致未定义的结果。


只有当你不小心(诚然非常小心)时,混合使用malloc/delete才会成为问题。 - Martin York

0

如果你在使用C语言(参考标签),我不确定为什么要使用new。

我会malloc我需要的数组单独的部分,然后在完成后释放它们。我想你不能释放你没有先malloc的东西。你也不能删除一个void指针。


0
注意,你还没有删除values[0]和values[1],这是一个内存泄漏。但是根据你的设计,你不能释放values[2],因为它是指向你的.data部分的指针。

0

你需要跟踪有多少 void* 最初是通过 calloc 分配的,然后迭代它们,逐个释放,最后再释放原始 values 变量。

格式出了点问题...(预览功能正常)。

int ct = 3;
values = (void*)calloc(ct,sizeof(void));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;

for ( int i = 0; i < ct; i++ ) [
    delete( values[i] );
}
free( values );

糟糕...请问有人能告诉我如何格式化一个代码块吗? - billjamesdev
put 4 spaces before each line - fizzer
真的,什么都不用做,它就会格式化代码...太棒了。感谢您的帮助。 - billjamesdev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接