【发布时间】:2020-04-19 11:50:39
【问题描述】:
我有这个宏:
/*
* int callocs(type **ptr, size_t nmemb);
*
* Safe & simple wrapper for `calloc()`.
*
* PARAMETERS:
* ptr: Memory will be allocated, and a pointer to it will be stored
* in *ptr.
* nmemb: Number of elements in the array.
*
* RETURN:
* 0: OK.
* != 0: Failed.
*
* FEATURES:
* - Safely computes the element size (second argument to `calloc()`).
* - Returns non-zero on error.
* - Doesn't cast.
* - The pointer stored in `*ptr` is always a valid pointer or NULL.
*
* EXAMPLE:
* #define ALX_NO_PREFIX
* #include <libalx/base/stdlib/alloc/callocs.h>
*
* int *arr;
*
* if (callocs(&arr, 7)) // int arr[7];
* goto err;
*
* // `arr` has been succesfully allocated here
* free(arr);
* err:
* // No memory leaks
*/
#define callocs(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
\
*ptr_ = calloc(nmemb, sizeof(**ptr_)); \
\
!(*ptr_); \
} \
)
我希望它是一个提高安全性的功能。这是第一个想法:
#define callocs(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
\
callocs__(ptr_, nmemb, sizeof(**ptr_)); \
} \
)
int callocs__(void **ptr, ptrdiff_t nmemb, size_t size)
{
if (nmemb < 0)
goto ovf;
*ptr = calloc(nmemb, size);
return !*ptr;
ovf:
errno = ENOMEM;
*ptr = NULL;
return ENOMEM;
}
但是编译器会抱怨:
error: passing argument 1 of callocs__ from incompatible pointer type [-Werror=incompatible-pointer-types]
note: in expansion of macro callocs
note: expected void ** but argument is of type struct My_Struct **
简单的显式转换为(void **) 安全吗?:
#define callocs(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
\
callocs__((void **)ptr_, nmemb, sizeof(**ptr_)); \
} \
)
我所说的安全是指从标准的角度来看(我猜不是)和从实现的角度来看(在这种特定情况下,GNU C)(我不确定)。
如果没有,void * 类型的中间指针是否足够?:
#define callocs(ptr, nmemb) ( \
{ \
__auto_type ptr_ = (ptr); \
void *vp_; \
int ret_; \
\
ret_ = callocs__(&vp_, nmemb, sizeof(**ptr_)) \
*ptr_ = vp_; \
ret_; \
} \
)
还有其他解决办法吗?
【问题讨论】:
-
这能回答你的问题吗? Is void** an acceptable type in ANSI-C?
-
@chux-ReinstateMonica 我的意思是将所有可以在函数中的代码移到一个函数中,剩下的(
sizeof(**ptr_),不能进入函数)进入不太危险的宏。 -
CacahueteFrito “但在 POSIX 上所有指针都具有相同的表示”您确定 POSIX 指定对象指针和函数指针具有相同的表示吗? IAC,我认为这只是这篇文章关注的对象指针。
-
@cacahuete:这是关于值的可转换性,而不是表示
-
"如果 nelem 或 elsize 为 0,则 应返回空指针或可成功传递给 free() 的唯一指针值。 "
标签: c pointers gcc malloc void-pointers