使用空指针在C中重新编程Calloc / Realloc

时间:2019-01-11 01:32:09

标签: c malloc realloc void-pointers calloc

我实际上是在学习C编程,而我的学校实际上不允许我们在不对其进行重新编程的情况下使用calloc / realloc。这就是为什么我要寻求帮助。

这是我的问题: 我想使用void *来使代码可重用,但是当我尝试遍历数组时遇到“解引用void *指针”问题。我无法选择最终指针的类型。

这是我的功能:

#include <stdlib.h>

void *my_calloc(size_t size, size_t n)              //n = number of bytes your type : sizeof(<whatever>)
{
    void *ptr = NULL;

    if (size < 1 || n < 1)
        return (NULL);
    ptr = malloc(n * (size + 1));
    if (ptr == NULL)
        return (NULL);
    for (int i = 0; i != (n * (size + 1)); i++) {
        *ptr = NULL;                                //Here is my problem
        ptr++;
    }
    return (ptr);
}

void *my_realloc(void *src, size_t size, size_t n)
{
    void *dst = NULL;
    int dst_len = 0;

    if (src == NULL || size < 0 || n < 1)
        return (NULL);
    dst_len = my_strlen(src) + size;
    if (dst_len == my_strlen(src))
        return (src);
    dst = my_calloc(dst_len, n);
    if (dst == NULL)
        return (NULL);
    for (int i = 0; src[i] != NULL;i++)
        dst[i] = src[i];                        //Here is the same problem...
    free(src);
    return (dst);
}

我在写帖子时发现一个问题,我的my_strlen函数只能使用一个字符* ...,所以我需要一个看起来像这样的函数my_strlen

int my_strlen(void *str)
{
    int len = 0;

    while (str[len] != NULL) {                //same problem again...
        len++;
    }
    return (len);
}

我调用calloc / malloc的典型函数是:

int main(void)
{
    char *foo = NULL;
    int size = 0;
    int size_to_add = 0;

    size = <any size>;
    //free(foo);                                //only if foo has been malloc before
    foo = my_calloc(size, typeof(*foo));

    //something

    size_to_add = <any size>;
    foo = my_realloc(foo, size_to_add, sizeof(*foo))

    //something

    free(foo);
    return (0);
}

感谢您尝试帮助我。

2 个答案:

答案 0 :(得分:2)

my_calloc()遇到各种麻烦:

void *上尝试过的指针数学

这是未定义的行为(UB)。
而是将ptr用作字符指针。

// void *ptr = NULL;
unsigned char *ptr = NULL;
...
ptr++;

试图取消引用void *

这也是UB。
而是将ptr用作字符指针。

// void *ptr = NULL;
unsigned char *ptr = NULL;
...
// *ptr = NULL;
*ptr = '\0';

my_calloc()分配的内存比calloc()

要与calloc()相同,请不要添加一个。

// ptr = malloc(n * (size + 1));
ptr = malloc(n * size);

无溢出保护

my_calloc()未检测到n * (size + 1)溢出。测试是

// Note: it is known n > 0 at this point
if (SIZE_MAX/n > size+1) return NULL;
// or if OP drop the + 1  idea, 
if (SIZE_MAX/n > size) return NULL;

my_realloc()遇到各种麻烦:

签名不同

我希望“学校实际上不允许我们在不对其进行重新编程的情况下使用calloc /重新分配”的目标是要创建一个realloc()而不是my_realloc()的替代品。如果需要其他功能,请考虑使用新名称

void *my_realloc(void *src, size_t size, size_t n)
// does not match
void *realloc(void *ptr, size_t size);

无法处理缩小的分配量

数据复制未考虑新分配可能小于先前分配的情况。这导致了UB。

不需要的代码

size < 0始终为假

内存泄漏

以下代码在返回之前不会释放src。此外,当n>0时,它不分配任何内容。这不同于calloc(pit, 0)calloc(NULL, 42)

// missing free, no allocation 
if (src == NULL || size < 0 || n < 1) {
    return (NULL);
}

假定为字符串

my_strlen(src)假设src指向有效字符串。 calloc()不认为那样。

答案 1 :(得分:0)

void是不完整的类型,因此您不能取消引用void *。但是,您可以将其强制转换为char *unsigned char *来访问各个字节。

因此my_calloc可以做到:

((char *)ptr)[i] = 0;

my_realloc可以做到这一点:

((char *)dst)[i] = ((char *)src)[i];