我正在研究我从研究团队请求的代码。我试图理解代码,然而,他们以一种奇怪的方式使用了malloc。这里;
在头文件中;
#define ERROR_OUTPUT stderr
#define FAILIF(b) { \
if (b) { \
fprintf(ERROR_OUTPUT, "FAILIF triggered on line %d, file %s. Memory allocated: %lld\n", \
__LINE__, __FILE__, totalAllocatedMemory); exit(1); \
} \
}
#define MALLOC(amount) \
( (amount > 0) ? totalAllocatedMemory += amount, malloc(amount) : NULL)
在cpp文件中;
double *memRatiosForNNStructs = NULL;
double *listOfRadii = NULL;
nRadii = 1;
FAILIF(NULL == (memRatiosForNNStructs = (double*)MALLOC(nRadii * sizeof(double))));
根据我的理解,他们定义的MALLOC意味着以下内容;
if(amount>0) // which is true; at least in this case
{
totalAllocatedMemory = totalAllocatedMemory + amount; // sounds reasonable
malloc(amount) // What?? This will leak memory...
}
else
{
NULL; // Do nothing? I guess that's fine
}
这里有什么我想念的吗?或者他们只是犯了一个(天真的)错误?
答案 0 :(得分:8)
您拥有的第三个代码段并不等效。请注意使用the comma operator:
#define MALLOC(amount) \
( (amount > 0) ? totalAllocatedMemory += amount, malloc(amount) : NULL)
^
N.B.!
逗号运算符接受两个参数,计算并丢弃第一个表达式,然后计算并返回第二个表达式。
ternary conditional operator以这种方式使用
a = ((b)?(c:d))
等同于此
if(b) {
a = c;
}
else {
a = d;
}
逗号运算符使用了这种方式
e = f, g;
等同于此
f;
e = g;
所以,如果你有
a = ((b)?(f,g:d))
然后相当于
if(b) {
f;
a = g;
}
else {
a = d;
}
在原始帖子中提供的代码中,MALLOC
宏将像这样使用:
memRatiosForNNStructs = (double*)MALLOC(nRadii * sizeof(double));
相当于:
// First operand of ternary conditional
if(nRadii * sizeof(double) > 0)
{
// Second operand of ternary conditional
// First expression of the comma operator
totalAllocatedMemory += nRadii * sizeof(double));
// Second expression of the comma operator
memRatiosForNNStructs = (double*)malloc(nRadii * sizeof(double));
}
else
{
// Third operand of ternary conditional
memRatiosForNNStructs = (double*)NULL;
}
老实说,这可以作为C中的函数实现,而不失一般性:
void* my_malloc(unsigned int amount)
{
if(amount > 0) {
// I assume this is a global variable
totalAllocatedMemory = totalAllocatedMemory + amount;
return malloc(amount);
}
else {
return NULL;
}
}
memRatiosForNNStructs = (double*)my_malloc(nRadii * sizeof(double));
所以我不确定将它作为一个难以阅读的宏实现的重点是什么。
答案 1 :(得分:3)
您正在处理逗号运算符,它按顺序计算每个操作数并返回最后一个操作数的返回值。因此a + b, malloc(n)
首先评估a + b
,然后评估malloc(n)
,然后返回后者的结果。因此整个三元条件表达式的返回类型是void *
。
三元表达式的最佳近似值是函数:
void * MALLOC(unsigned int n) {
if (n > 0) {
totalAllocatedMemory += n;
return malloc(n);
} else {
return NULL;
}
}
答案 2 :(得分:1)
他们正在使用三元运算符和逗号运算符的混淆组合。
请记住:
因此,如果amount>0
,表达式将返回totalAllocatedMemory += amount, malloc(amount)
;由于逗号运算符执行两个表达式但仅返回第二个表达式,因此表达式的最终返回值是malloc
中的值。
但是,如果它是一个内联函数,那个丑陋的宏会更清晰(并且没有性能损失)。
答案 3 :(得分:1)
MALLOC
宏与您的扩展程序不完全相同。
在条件为真的情况下,三元运算符将返回由malloc
调用返回的指针,如果条件为假,则返回NULL指针。
只要您将三元运算符的结果分配给可变量,就不存在任何记忆泄漏。