我正在研究SslSplit code。我在opts.h
文件中遇到了一些陌生的,奇怪的函数声明。这些函数的定义非常简单,但是我可以使用一些有关声明的帮助。在这里:
opts.h:
char *proxyspec_str(proxyspec_t *) NONNULL(1) MALLOC;
void opts_set_crl(opts_t *, const char *) NONNULL(1,2);
opts.c:
void
opts_set_crl(opts_t *opts, const char *optarg)
{
if (opts->crlurl)
free(opts->crlurl);
opts->crlurl = strdup(optarg);
log_dbg_printf("CRL: %s\n", opts->crlurl);
}
char *
proxyspec_str(proxyspec_t *spec)
{
char *s;
char *lhbuf, *lpbuf;
char *cbuf = NULL;
// Some code..
return s;
}
attrib.h:
#define WUNRES __attribute__((warn_unused_result))
#define MALLOC __attribute__((malloc)) WUNRES
#define NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
我的问题是,函数声明末尾的NONNULL和MALLOC是什么意思?
答案 0 :(得分:3)
正如您指出的那样,NONNULL
和MALLOC
只是
宏。它们的替换以__attribute__
开始,
是编译器扩展关键字,用于定义属性
在功能上。
__VA_ARGS__
代替变量号
宏中的参数(用...
声明)。所以这
声明:
void opts_set_crl(opts_t *, const char *) NONNULL(1,2);
由预处理器转换(在编译器看到之前 它):
void opts_set_crl(opts_t *, const char *) __attribute__((nonnull(1,2)));
这实际上是在防止第一个和第二个
第二个参数为NULL
。如果您检查
支持此扩展的编译器文档,
例如gcc或clang,您将找到完整的
说明。
GNU manual中的另一个属性malloc
:
这告诉编译器函数类似于malloc,即 该函数返回的指针P不能为其他任何指针加上别名 函数返回时有效,而且没有指向有效的指针 对象出现在P寻址的任何存储中。
使用此属性可以改善优化。像malloc这样的函数 和calloc具有此属性,因为它们返回一个指向 未初始化或清零的存储。但是,像realloc这样的函数 没有此属性,因为它们可以返回指向存储的指针 包含指针。