通过两种方式检查malloc返回值的有效方法:
-
使用宏
#define ALLOC(p,n) do{ *p=malloc(n*sizeof **p); } while(0)
-
用户定义功能
static inline void *MallocOrDie(size_t MemSize) { void *AllocMem = malloc(MemSize); /* Some implementations return null on a 0 length alloc, * we may as well allow this as it increases compatibility * with very few side effects */ if(!AllocMem && MemSize) { printf("Could not allocate memory!"); exit(-1); } return AllocMem; }
在不同的情况下,这更有效。
注意:不想使用calloc而不是malloc,因为不想更改API的
由于您不想更改API,请考虑使用new[]
和delete[]
这两种更简单的方法。如果您没有安装异常处理程序,如果new
失败,将立即调用std::terminate
,因此您不需要手动检查。
#define ALLOC(p,n) *(p) = MallocOrDie((n) * sizeof *(p))
static inline void* MallocOrDie(size_t MemSize) {
return new char[MemSize];
}
static inline void Free(void* p) {
delete [] static_cast<char*>(p);
}
或者作为宏的替代:
template<class T>
void ALLOC(T*& p, size_t n) { p = new T[n]; }
template<class T>
void FREE(T* p) { delete[] p; }
然而,这不是应该做的。为多个元素而不是bytes分配空间。如果您需要10
int
的空间,但不喜欢零初始化它们的额外成本,请使用std::make_unique_for_overwrite
:
auto array = std::make_unique_for_overwrite<int[]>(10);
这会更改API(它应该更改(,因为您现在得到的是std::unique_ptr<int[]>
而不是void*
,但它的好处是,当array
超出范围时,它将自动被delete[]
编辑,因此需要担心的问题会减少很多。你也可以直接索引这个智能指针,而不需要强制转换,所以
{
auto array = std::make_unique_for_overwrite<int[]>(10);
array[9] = 123;
}
而不是
{
int* array = static_cast<int*>(MallocOrDie(10 * sizeof *array));
array[9] = 123;
Free(array);
}
但是,我建议您使用std::vector
。它只需要零初始化而不是默认初始化,但除非你注意到有问题,否则不要放弃这个想法。通过按值(复制它们(而不是按引用来传递(这至少和四处传递指针一样便宜(,很容易滥用std::vector
,这使得新的C++程序员不愿意使用它们。只要学会它们,编程生活就会轻松很多。
std::vector<int> array(10);