重新分配先前分配的指向 SIZE_MAX 的指针不会设置 ENOMEM,但重新分配 NULL 可以吗?

问题描述 投票:0回答:1

问题:

我正在重写一些 malloc 函数(

malloc
calloc
realloc
free
),我决定实现一些单元测试,希望能让自己的事情变得更容易一些这条线(而且这似乎是很好的做法)。

当我进行设置时,我使用标准的“分配”来确保测试正确运行。不幸的是,我在以下测试中遇到了问题:

#include "unity.h"

#include <stdlib.h>
#include <errno.h>

#include "nmalloc.h"

void realloc_overflow(void)
{
    // Reset ERRNO
    errno = 0;

    // Verify allocating SIZE_MAX sets ENOMEM when reallocating NULL
    TEST_ASSERT_EQUAL_PTR(NULL, my_realloc(NULL, SIZE_MAX)); // <-- Sets ENOMEM
    TEST_ASSERT_ERRNO(ENOMEM);

    // Allocate 112 bytes
    void* ptr = my_malloc(ALLOC_LEN_112U);
    TEST_ASSERT_TRUE(ptr != NULL);

    // Reset ERRNO
    errno = 0;

    // Verify allocating SIZE_MAX sets ENOMEM when reallocating a valid pointer
    // ! This doesn't set errno to ENOMEM on my system? However (SIZE_MAX + 1) does?
    TEST_ASSERT_EQUAL_PTR(NULL, my_realloc(ptr, SIZE_MAX));

    TEST_ASSERT_ERRNO(ENOMEM);

    my_free(ptr);
}

这给出了意想不到的输出:

test/Test-nmalloc.c:326:realloc_overflow:FAIL: Expected 12 Was 0

但奇怪的是,使用

realloc(valid_ptr, SIZE_MAX + 1)
显示了设置
errno = ENOMEM
的预期行为?

注意:如果它变得重要,我将在 M1 Mac 上测试所有这些

尝试解决方案:

我做了一个最小可行的例子:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#include "nmalloc.h"

#define ALLOC_LEN_112U 112U

int main(void)
{
    errno = 0;

    // TEST_ASSERT_EQUAL_PTR(NULL, my_realloc(NULL, SIZE_MAX));
    if (NULL == realloc(NULL, SIZE_MAX))
        printf("PASS: null_ptr is NULL.\n");
    else
    {
        printf("ERR: null_ptr is not NULL!\n");
        return 1;
    }

    // TEST_ASSERT_ERRNO(ENOMEM);
    if (errno == ENOMEM)
        printf("PASS: errno is ENOMEM.\n");
    else
    {
        printf("ERR: errno is not NULL!\n");
        return 1;
    }

    void *valid_ptr = malloc(ALLOC_LEN_112U);

    // TEST_ASSERT_TRUE(ptr != NULL);
    if (valid_ptr == NULL)
    {
        printf("ERR: valid_ptr is NULL!\n");
        return 1;
    }
    else
        printf("PASS: valid_ptr is not NULL.\n");

    errno = 0;

    // TEST_ASSERT_EQUAL_PTR(NULL, realloc(ptr, SIZE_MAX));
    if (NULL == realloc(valid_ptr, SIZE_MAX))
        printf("PASS: invalid_ptr is NULL.\n");
    else
    {
        printf("ERR: invalid_ptr is not NULL!\n");
        return 1;
    }

    // TEST_ASSERT_ERRNO(ENOMEM);
    if (errno == ENOMEM)
        printf("PASS: errno is ENOMEM.\n");
    else
    {
        printf("ERR: errno is not NULL!\n");
        return 1;
    }

    free(valid_ptr);

    printf("Success!");
}

这给出了正确的预期输出???

[user@machine ~/test] % clang alloc-test.c nmalloc.o -I./lib -o alloc-test.o && ./alloc-test.o
PASS: null_ptr is NULL.
PASS: errno is ENOMEM.
PASS: valid_ptr is not NULL.
PASS: invalid_ptr is NULL.
PASS: errno is ENOMEM.
Success!
[user@machine ~/test] % 

即使包含

jemalloc
库(即添加
#include <...>
,而不仅仅是将其添加到 clang),一切似乎都正常。所以在这一点上,我不完全确定这里发生了什么,所以一些见解将非常感激。也许我只是错过了一些微妙(或明显)的东西?

谢谢! :)

c malloc errno jemalloc unity-test-framework
1个回答
0
投票
  1. SIZE_MAX 不是可分配的最大内存大小,仅是

    size_t
    可以容纳的最大值。
    (SIZE_MAX + 1) == 0
    并且
    realloc
    的行为是由 实现定义的

  2. SIZE_MAX
    远远超过了Linux 64中的128TB虚拟内存。所以
    malloc
    家庭功能将会失败。

© www.soinside.com 2019 - 2024. All rights reserved.