简体   繁体   English

为什么使用malloc这样?

[英]Why was malloc used this way?

I'm working on a code I requested from a researching team. 我正在按照研究小组的要求编写代码。 I'm trying to understand the code, however, they used malloc in a strange way. 我试图理解代码,但是,他们以奇怪的方式使用了malloc。 here; 这里;

in the header file; 在头文件中;

 #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)

in the cpp file; 在cpp文件中;

 double *memRatiosForNNStructs = NULL;
 double *listOfRadii = NULL;
 nRadii = 1;
 FAILIF(NULL == (memRatiosForNNStructs = (double*)MALLOC(nRadii * sizeof(double))));

From my understanding, the MALLOC that they defined means the following; 根据我的理解,他们定义的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
}

Is there something that I'm missing here? 我在这里缺少什么吗? Or did they just make a (naive) mistake? 还是他们只是犯了一个(幼稚的)错误?

The third code snippet you have is not equivalent. 您拥有的第三个代码段不相等。 Notice the use of the comma operator : 注意使用逗号运算符

#define MALLOC(amount) \
    ( (amount > 0) ? totalAllocatedMemory += amount, malloc(amount) : NULL)  
                                                   ^
                                                  N.B.!

The comma operator takes two arguments, evaluates and discards the first expression, then evaluates and returns the second expression. 逗号运算符有两个参数,求值并放弃第一个表达式,然后求值并返回第二个表达式。

The ternary conditional operator used this way 三元条件运算符使用这种方式

a = ((b)?(c:d))

is equivalent to this 相当于这个

if(b) {
    a = c;
}
else {
    a = d;
}

The comma operator used this way 逗号运算符使用这种方式

e = f, g;

is equivalent to this 相当于这个

f;
e = g;

So if you have 所以如果你有

a = ((b)?(f,g:d))

then that is equivalent to 那等于

if(b) {
    f;
    a = g;
}
else {
    a = d;
}

In the code provided in your original post, the MALLOC macro is to be used like this: 在原始帖子提供的代码中,将使用MALLOC宏,如下所示:

memRatiosForNNStructs = (double*)MALLOC(nRadii * sizeof(double));

which is equivalent to this: 这等效于:

   // 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;
}

Honestly though, this could be achieved as a function in C with no loss of generality: 坦白地说,这可以作为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));

So I'm not sure what's the point of even implementing it as a hard-to-read macro. 因此,我不确定将其实现为难以读取的宏有什么意义。

You're dealing with the comma operator , which evaluates each operand in order and returns the return value of the last operand. 您正在处理逗号运算符 ,该运算符按顺序评估每个操作数,并返回最后一个操作数的返回值。 So a + b, malloc(n) first evaluates a + b , then malloc(n) , and then returns the result of the latter. 因此, a + b, malloc(n)首先计算a + b ,然后是malloc(n) ,然后返回后者的结果。 So the return type of the entire ternary conditional expression is void * . 因此,整个三元条件表达式的返回类型为void *

The best approximation to the ternary expression is a function: 三元表达式的最佳近似是一个函数:

void * MALLOC(unsigned int n) {
   if (n > 0) {
      totalAllocatedMemory += n;
      return malloc(n);
   } else {
      return NULL;
   }
}

They are using a confusing combination of the ternary operator and of the comma operator. 他们正在使用三元运算符和逗号运算符的混淆组合。

Keep in mind that: 请记住:

  • the ternary operator evaluates its first operand and returns the second if the first is true, otherwise the third; 三元运算符计算其第一个操作数,如果第一个为真,则返回第二个,否则为第三个;
  • the comma operator evaluates both its operands and returns the second. 逗号运算符计算两个操作数并返回第二个。

Thus, if amount>0 , the expression will return totalAllocatedMemory += amount, malloc(amount) ; 因此,如果amount>0 ,则表达式将返回totalAllocatedMemory += amount, malloc(amount) ; since the comma operator executes both expressions but returns only the second, the final return value of the expression is the one from the malloc . 由于逗号运算符执行两个表达式,但仅返回第二个表达式,因此该表达式的最终返回值是malloc的一个。

Still, that ugly macro would have been much clearer (and with no performance loss) if it were an inline function. 但是,如果它是内联函数,则该丑陋的宏将更加清晰(并且不会造成性能损失)。

The MALLOC macro is not quite the same as your expansion. MALLOC宏与您的扩展不太相同。

The ternary operator will return the pointer returned by the call to malloc in the case that the condition is true, and a NULL pointer in the case that the condition is false. 如果条件为true,则三元运算符将返回调用返回的malloc指针;如果条件为false,则返回NULL指针。

As long as you assign the result of the ternary operator to a vairable there's no memeory leak. 只要将三元运算符的结果分配给可变变量,就不会有内存泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM