简体   繁体   English

使用 calloc() 为 0 个元素分配内存?

[英]memory allocation for 0 elements with calloc()?

Actually I expected a warning / an error here but it compiles without any problems.实际上,我希望这里有一个警告/错误,但它编译没有任何问题。 Why is it possible to call a calloc-function with 0 objects as first argument?为什么可以使用 0 个对象作为第一个参数调用 calloc 函数? And why does it allocate memory for this?为什么它为此分配内存?

int* p_integer=calloc(0, sizeof(int));

if(!p_integer){
    exit(EXIT_FAILURE); 
}

//prints 4 
printf("size *p_integer: %zu\n", sizeof(*p_integer));

OK, some additions:好的,补充几点:

void* calloc( size_t num, size_t size );


Allocates memory for an array of num objects of size and initializes all bytes in the 
allocated storage to zero.

If allocation succeeds, returns a pointer to the lowest (first) byte in the allocated 
memory block that is suitably aligned for any object type.

If size is zero, the behavior is implementation defined (null pointer may be returned, 
or some non-null pointer may be returned that may not be used to access storage) 

https://en.cppreference.com/w/c/memory/calloc https://en.cppreference.com/w/c/memory/calloc

How to understand that?这怎么理解? In my case is the size (second parameter) not zero, right?在我的情况下,大小(第二个参数)不为零,对吗? So there is no explanation for the case if the first parameter == zero.因此,如果第一个参数 == 零,则没有对这种情况的解释。 Or do I have to calculate 0*sizeof(int) == 0 (size of requested memory block).或者我是否必须计算 0*sizeof(int) == 0(请求的内存块的大小)。 Which "size" do they mean?他们是什么“尺寸”?

Why is it possible to call a calloc-function with 0 objects as first argument?为什么可以使用 0 个对象作为第一个参数调用 calloc 函数? (OP) (OP)

It is possible because the C spec for the library says it is allowed.这是可能的,因为库的 C 规范说它是允许的。 Yet memory allocations of 0 are an edge case that results in implementation-defined behavior .然而,内存分配为 0 是一种边缘情况,会导致实现定义的行为

C17/18 was recently updated in this area to: C17/18 最近在该领域更新为:

If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.如果请求的空间大小为零,则行为是实现定义的:要么返回空指针以指示错误,要么行为就好像大小是某个非零值一样,但不应使用返回的指针访问一个对象。 C17dr § 7.22.3 1 C17dr § 7.22.3 1


And why does it allocate memory for this?为什么它为此分配内存? (OP) (OP)

There is no evidence that any memory was allocated, just that a non- NULL pointer was returned for OP.没有证据表明分配了任何内存,只是为 OP 返回了一个非NULL指针。 It can't be used to reference any memory.它不能用于引用任何内存。

do I have to calculate 0*sizeof(int) == 0 (size of requested memory block).我是否必须计算 0*sizeof(int) == 0(请求的内存块的大小)。 Which "size" do they mean?他们是什么“尺寸”?

The "size" is the product (without size_t range limitation). “大小”是产品(没有size_t范围限制)。 The size of an object is never 0 including sizeof(int) , so only the n needs testing.对象的大小从不为 0 包括sizeof(int) ,因此只有n需要测试。 With calloc(n, sz) , where both are variables, I would test with if (n == 0 || sz == 0) rather than perform multiplication which brings in overflow issues.使用calloc(n, sz) ,其中两者都是变量,我将使用if (n == 0 || sz == 0)进行测试,而不是执行会带来溢出问题的乘法。


To avoid this implementation defined behavior, test arguments first.为了避免这种实现定义的行为,首先测试参数。 Example:例子:

int *p = (n > 0) ? calloc(n, sizeof *p) : malloc(1);
if (p == NULL) Oops();
...
free(p);

Alternatively, to account for implementation defined behavior, perhaps not error on calloc(0, sizeof *p) returning NULL .或者,为了说明实现定义的行为,可能不是calloc(0, sizeof *p)返回NULL出错。

int *p = calloc(n, sizeof *p);
if (p == NULL && n > 0) Oops();
...
free(p);

[This answer addresses the reason we would want calloc and malloc to provide zero bytes of memory when requested. [这个答案解决了我们希望callocmalloc在请求时提供零字节内存的原因。 It does not address what the C standard says about it.]它没有解决 C 标准对它的描述。]

Consider writing a program that examines some input and perhaps categorizes various things, making lists of data in category C1, C2, and so on.考虑编写一个程序来检查一些输入并可能对各种事物进行分类,制作类别 C1、C2 等中的数据列表。 Later, the software will process all the data for C1, then all the data for C2, and so on.稍后,软件将处理 C1 的所有数据,然后处理 C2 的所有数据,依此类推。

Consider which is simpler and shorter:考虑哪个更简单和更短:

  • The program allocates space for N list items and processes N list items, and this code works whether N is zero or positive.该程序为N 个列表项分配空间并处理N 个列表项,无论N是零还是正数,此代码都有效。
  • The program must explicitly test N and use different code paths depending on whether N is zero or positive.程序必须明确测试N并根据N是零还是正数使用不同的代码路径。

The former choice is simpler, shorter, and cleaner.前一种选择更简单、更短、更干净。 Generally, it offers less opportunity for bugs.通常,它为错误提供的机会较少。 When software must have different paths based on whether N is zero or positive, there is a chance a programmer might overlook the zero case, resulting in a bug.当软件必须根据N是零还是正数而有不同的路径时,程序员可能会忽略零的情况,从而导致错误。

zero sized malloc, calloc is 100% OK.零大小的 malloc,calloc 是 100% OK。 free is OK free就OK

sizeof of the p_integer or *p_integer is not using dereferencing the pointer - it is 100% OK p_integer*p_integer sizeof没有使用取消引用指针 - 它是 100% OK

you can assign any value to the p_integer - but if malloc or calloc returns valid not NULL pointer it will result in the potential memory leak;您可以为p_integer分配任何值 - 但如果 malloc 或 calloc 返回有效的非空指针,它将导致潜在的内存泄漏;

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

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