首页 > 解决方案 > 通过动态分配创建数组后,在C中通过realloc改变内存大小时出现问题

问题描述

我正在练习C语言。

我想使用动态分配仅使用我输入的字符串的大小作为内存并检查输入字符串是否正确保存。

因此,我使用 malloc 和 realloc 函数编写了以下代码。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 


void str_copy(char* str_array_f) {

    void* tmp;
    char buf;
    unsigned char arr_size = 1; 
    unsigned char arr_cur = 0;

    while ((buf = getchar())) {
        if (buf == '\n') {
            break;
        }
        str_array_f[arr_cur++] = (char)buf;

        tmp = realloc(str_array_f, ((arr_size++) * sizeof(char)) + sizeof(char));
        if (tmp != 0) {
            str_array_f = tmp;
        }
        else {
            printf("memory leak error occur! \n");
            break;
        }
    }
    str_array_f[arr_size - 1] = 0x00; 
    
}


void main() {

    int contiune = 1;

    while (contiune) {
        char* str_array = malloc(sizeof(char) + sizeof(char));

        printf("Please type something : ");
        str_copy(str_array);

        printf("'str_array' have this : %s \n", str_array);
        printf("-------------------------------------------------\n");
        if (str_array[0] == '1') {
            contiune = 0;
        }
        free(str_array);
    }

}

并且,作为性能的结果,出现了以下问题。

  1. 有时从间歇打印值的第 5 个字符开始出现奇怪的值(要重现此问题,建议删除 while 循环并重复尝试) 在此处输入图像描述

  2. 在使用while循环重复接收一个值的情况下,重复4次后出现错误。在此处输入图像描述

  3. 如果 tmp 分配的内存是一个 void 类型的指针,在第 22 行之后被释放(例如,'free(tmp);'),执行时,没有输出,立即出错。 在此处输入图像描述

对于上述 3 个问题,我不确定是什么原因以及如何解决。

请让我知道是否有解决方案。

而且,如果我的代码在效率或各个方面有不好的编码方法,如果您告诉我,我将不胜感激。

*编程执行环境:Visual Studio 2019

标签: c

解决方案


为了解释你做错了什么我将在这里使用一个最小的例子

void change_x(int x) {
    x = 2;
}

int main() {
    int x = 1;
    change_x(x);
    printf("%i\n", x); // it'll print 1 not 2
    return 0;
}

这里的整数x是在调用函数时复制的,改变它并不会真正改变xin main。同样,您在代码中所做的str_array_f = tmp;实际上不会更改str_array复制的值。并且您正在尝试释放之前重新分配的指针。

上面示例的修复方法是不传递值 x 而是传递 x 的地址(这相当于在其他语言中通过引用传递)

void change_x(int* x) {
    *x = 2;
}

int main() {
    int x = 1;
    change_x(&x);
    printf("%i\n", x); // it'll print 1 not 2
    return 0;
}

并为您的代码

void str_copy(char** str_array_f) {...} // change the parameter
*str_array_f = tmp; // de reference and use it.

str_copy(&str_array); // call with it's address

还有一件事,不要更频繁地重新分配它不是有效的。相反,只需分配具有最小大小的“数组”类型,当它被填满时,重新分配它的 2 倍大小(或 1.5,如果你愿意)


推荐阅读