c++中的malloc/free:为什么free不接受const void*,有没有更好的方法?
malloc/free in C++: why does free not accept a const void*, and is there a better way?
将c++ 11代码接口到一些C回调,并且我必须传递const char * const *
,即字符串数组。以下是我的代码的精简版本:
int main(int,char**){
const int cnt = 10;
const char * const * names =
static_cast<const char * const *>(malloc( sizeof(char*) * cnt));
//... allocating names[0], etc. coming soon ...
the_c_function(names);
free(names);
return 0;
}
所以我想出了如何在c++中使用malloc
,但我被困在free
上,因为它告诉我:"从' const void* '到' void* '的无效转换[-fpermissive]"
free( const_cast<void*>(names) );
free( static_cast<void*>(acctnames) );
。"从' const char* const* '类型转换为' void* '类型无效".
所做的工作是一个很好的'ole C cast:
free( (void*)(acctnames) );
这是安全的,还是我错过了什么?(valgrind
告诉我"所有堆块都被释放了——没有泄漏是可能的",这是一些安慰!)
注:在Linux上使用g++ 4.8.1
UPDATE:为什么free()
想要一个非const指针的解释在这里:无法释放C中的const指针(尽管我发现巴拉克·马诺斯的回答更清楚)
const_cast
只能删除const
和volatile
限定符;它不能改变指针类型。相反,static_cast
可以更改类型,但不能删除顶级限定符。但是,从非const对象指针类型转换为void*
是隐式的,因此应该可以工作:
free( const_cast<const char**>(names) );
更棘手的转换,将需要const_cast
和static_cast
(甚至reinterpret_cast
在奇怪的情况下)。
邪恶的C可以结合const_cast
和static_cast
,所以可以作为两者的快捷方式使用。然而,这是一个坏主意,因为它更危险:如果您指定了错误的类型,那么它将通过reinterpret_cast
强制转换,可能导致奇怪的运行时行为,其中更安全的强制转换将在编译时失败。
但是,这里不需要任何强制类型转换:从X*
到X const*
的转换可以隐式地完成,因此只需更改本地指针的类型:
const char ** names = static_cast<const char **>(malloc( sizeof(char*) * cnt));
the_c_function(names); // OK - adds const
free(names); // OK - no const to remove
最后,由于这是c++,根本不需要在malloc
和指针上瞎折腾(除非C API足够邪恶,要求从malloc
中分配内存):
std::vector<const char*> names(cnt);
the_c_function(names.data());
为了支持动态内存,堆被实现为内存块的链表,其中列表中的每个块存储列表中下一个块的地址。
调用free(p)
时,它将地址p
处的值设置为列表中第一个块的地址,然后将列表中第一个块的指针设置为p
的值。
:
static void* _head;
...
void free(void* p)
{
*(int*)p = (int)_head;
_head = p;
}
显然,第一个赋值不能应用于const void* p
。
根据堆的实现,这可以应用于第一个块(_head
)或最后一个块(_tail
)。但是原则是一样的,p
不能被假定为const
(这意味着它可能指向一个只读内存段)。
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 遇到新行时,有没有办法停止istream_iterator
- 有没有一种方法可以在编译时获得作用域类名
- conan有没有办法导出一个空目录
- 对于C++中使用智能指针的指针算术限制,有没有一种变通方法
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 有没有可能有一个只有ADL才能找到的非好友功能
- 有没有办法从非C/C++文件中读取C++原始字符串文字的内容
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- 有没有办法知道Tracer是否成功地完全连接到了jaegerclientcpp中的jaeger后端服务器
- catch框架有没有办法比较流或文件
- 有没有任务栏API可以立即应用注册表更改
- 铸造标准::有没有回到原来的类型
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- c++中的malloc/free:为什么free不接受const void*,有没有更好的方法?