【问题标题】:I can't free the memory我无法释放内存
【发布时间】:2022-01-22 10:55:01
【问题描述】:

我是教职的第一年,我有这个作业:

编写一个程序,读取 n 个字符数组并将它们连接到另一个动态分配的数组中。根据用户的需要重复该操作多次。

每次显示结果后,分配的内存都会被释放。

这就是我所做的:

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

int main()
{
    char** p, * v;
    int n, m;
    printf("\n\t enter the number of the arrays : \t");
    scanf("%d", &n);
    printf("\n\t enter the maximum lenght of the arrays :");
    scanf("%d", &m);
    p = (char**)malloc(sizeof(char) * n);

    for (int i{}; i < n; i++)
        p[i] = (char*)malloc(sizeof(char) * m);

    char t = 'Y';
    while (t == 'Y')
    {
        size_t z = 0;
        printf("\n\t enter your arrays :");
        for (int i{}; i < n; i++) {
            scanf("%s", p[i]);
            z += strlen(p[i]);
        }
        v=(char* )malloc(z * sizeof(char));
        for (int i{}; i < n; i++)
            if (i == 0)
                strcpy(v, p[i]);
            else
                strcat(v, p[i]);
        if (v) {
            puts(v);
            free(v);
        }

        if (p)
            for (int i{}; i < n; i++)
                free(p[i]);

        printf("\n\t wanna continue ? (Y/N)");
        scanf("%d", &t);
    }
}

当我想释放内存以再次使用时,我从调试器中收到“磁头损坏错误”。

知道为什么吗?

【问题讨论】:

  • 通过 valgrind 运行您的代码。如果你对内存管理不善,它会告诉你在哪里。
  • p = (char**)malloc(sizeof(char) * n); 必须是 p = malloc(sizeof(char *) * n); 或者更好的是 p = malloc(sizeof(*p) * n);
  • 这似乎是C。编辑您的帖子以消除C++ 标签。
  • @0___________ 是的,但 OP 可能没有意识到这一点。 OP 需要弄清楚他们真正想要编码和编译的语言并首先对其进行排序。如果它是 C++ 那么很好,更新问题来说明这一点。如果是 C,则需要正确设置 IDE 才能执行此操作。
  • 你已经释放了p[i],但是你永远不会用free(p);跟进它。请记住,每次调用malloc(),都应该有一个对应的free()调用跨度>

标签: c


【解决方案1】:

更新:我做到了! 这是最终的代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include <stdbool.h>
bool ver(bool);

int main()
{
    int n, m;
    char** myarray;
    bool y = true;


    while (y == true) {
        printf("enter the number of arrays : ");
        scanf("%d", &n);
        myarray = malloc(n * sizeof(char*));
        if (myarray == NULL && n > 0) {
            fprintf(stderr, "Allocation failed\n");
            exit(1);
        }
        printf("enter the  maximum size of the  arrays : ");
        scanf("%d", &m);
        for (int i = { 0 }; i < n; i++)
            myarray[i] = malloc(m * sizeof(char));


        printf("\n\t enter your stings : \n");
        size_t x = 0;
        for (int i = 0; i < n; i++)
        {
            if (myarray[i])
                scanf("%s", myarray[i]);
            x += sizeof(myarray[i]);
        }
        char* v;
        v = malloc(x * sizeof(char));
        if (v == NULL && x > 0) {
            fprintf(stderr, "Allocation failed\n");
            exit(1);
        }
        strcpy(v, myarray[0]);
        for (int i = 1; i < n; i++)
            strcat(v, myarray[i]);
        puts(v);
        free(v);
        for (int i = 0; i < n; i++)
            free(myarray[i]);
        free(myarray);
        y = ver(y);



    }
}
bool ver(bool r) {
    char var;
    printf("\n\twanna continue ? (Y/N)\n");
    scanf(" %c", &var); 
    while(var != 'Y' && var != 'N')
    {
        printf("\n\tInvalid input  !\n wanna continue ?(Y/N).");
        scanf(" %c", &var);
    }

    if (var == 'N')
        r = false;
    else
        r= true;
    return r;
} 

我还是 C 的新手,如果你有什么建议请告诉。

【讨论】:

    【解决方案2】:

    分配大小错误

    代码分配了错误的大小。 p 是一个指针,而不是 char。 也不需要演员表。

    char** p; 
    ...
    p = (char**)malloc(sizeof(char) * n);  // Bad
    

    大小为被引用对象的类型。正确编码、审查和维护比尝试编码匹配类型更容易。

    p = malloc(sizeof *p * n);  // Good
    ...
      p[i] = malloc(sizeof *p[i] * m);
    

    健壮的代码也会检查错误。

    if (scanf("%d", &n) != 1 || n < 0) {
      fprintf(stderr, "No numeric input or negative count\n");
      // Perhaps exit here.
    }
    
    p = malloc(sizeof *p * n);
    if (p == NULL && n > 0) {
      fprintf(stderr, "Allocation failed\n);
      // Perhaps exit here.
    }
    

    可能存在其他problems

    1-1

    v under 分配 1,因为它不考虑终止 null 字符。这也适用于p[i] = malloc(sizeof *p[i] * m);,它可能应该是p[i] = malloc(sizeof *p[i] * (m+1));

        // size_t z = 0;
        size_t z = 1;
    

    简化

    而不是i==0 的特殊情况,只需先设置v[0] = 0

        v = malloc(sizeof *v * z /* or z + 1, see above */ );
        if (v) {
          // Handle error
        }
        v[0] = '\0';
        for (int i = 0; i < n; i++) {
          strcat(v, p[i]);
        }
        puts(v);
        free(v);
    

    其他简化和improvements 可能。

    【讨论】:

    • 我收到错误“E0513 如果我不使用强制转换,则无法将类型为“void *”的值分配给类型为“char **”的实体。
    • @RăzvanCâcu 为 C 代码使用 C 编译器。 “void *”不能分配给“char **”类型的实体表示您正在使用 C++ 编译器。
    • @RăzvanCâcu - VS 必须具有允许编译 C 的设置,不是吗?
    • @RăzvanCâcu 询问您的老师是否应该使用 C 模式的编译器编译您的 C 代码,或者使用默认设置和其他语言的编译器。
    • @Neil 是的,我做到了。
    【解决方案3】:

    我收到警告,也许我忘记了一些检查 (malloc/scanf)。

    虽然我是初学者,但希望对你有所帮助。

    #define _CRT_SECURE_NO_WARNINGS
    
    #include<stdio.h>
    #include<string.h>
    #include<malloc.h>
    #include<stdlib.h>
    #include<stdbool.h>
    
    struct cstring {
    
        char* data;
        size_t size;
    
    };
    
    bool create_cstring(struct cstring* const object, const size_t size) {
    
        return (object->data = calloc(size, sizeof(char))) ?
            (object->size = size + 1U) :
            (object->size = 0U);
    
    }
    
    bool destroy_cstring(struct cstring* const object) {
    
        free(object->data);
        object->size = 0U;
    
    }
    
    struct cvector_string {
    
        struct cstring* data;
        size_t size;
    
    };
    
    bool create_cvector_string(struct cvector_string* const object, const size_t size) {
    
        return (object->data = calloc(size, sizeof(struct cstring))) ?
            (object->size = size) :
            (object->size =   0U) ;
    
    }
    
    void destroy_cvector_string(struct cvector_string* const object) {
    
        free(object->data);
        object->size = 0U;
    
    }
    
    int main()
    {
    
        struct cvector_string cv = { NULL, 0U };
    
        // Allocations 
        {
    
            // Allocate n arrays of chars
            {
    
                size_t cv_n = 0;
    
                printf("\n\t Enter the number of the arrays : \t"); 
                scanf("%zu", &cv_n);
    
                if (!create_cvector_string(&cv, cv_n)) {
    
                    fprintf(stderr, "Error : Bad allocation\n");
                    return 1;
    
                }
    
            }
    
            // Allocate arrays of n chars
            {
    
                size_t cv_m = 0;
    
                printf("\n\t Enter the maximum lenght of the arrays : \t");
                scanf("%zu", &cv_m);
    
                for (struct cstring* it = cv.data; it != cv.data + cv.size; ++it) {
    
                    if (!create_cstring(it, cv_m)) {
    
                        fprintf(stderr, "Error : Bad allocation\n");
                        return 1;
    
                    }
    
                }
    
            }
    
        }
    
        struct cstring r = { NULL, 0U };
    
    
        {
    
            char cont = '\0';
    
            do {
    
                /* Initialize arrays of chars, calculate the length of the resulting string
                 * and create the resulting string */
                {
    
                    size_t length_sum = 0;
    
                    for (struct cstring* it = cv.data; it != cv.data + cv.size; ++it) {
    
                        scanf("%s", it->data);
                        length_sum += strlen(it->data);
    
                    }
    
                    if (!create_cstring(&r, length_sum)) {
    
                        fprintf(stderr, "Error : Bad allocation\n");
                        return 1;
    
                    }
    
                }
    
                // Initialize and concatenate the resulting string
                {
    
                    strcpy(r.data, cv.data[0].data); 
                    // or using destination = strcpy(malloc, source), same for strcat
    
                    for (struct cstring* it = cv.data + 1; it != cv.data + cv.size; ++it) strcat(r.data, it->data);
    
                }
    
    
                // Print and deallocate the resulting string
    
                puts(r.data);
                destroy_cstring(&r);
    
                // Prompt to continue
    
                printf("\n\t Wanna continue? (Y/N) ");
                scanf(" %c", &cont);
    
            } while (cont == 'Y');
    
        }
    
        // Deallocations 
        {
    
            // Deallocate all the arrays of chars
            for (struct cstring* it = cv.data; it != cv.data + cv.size; ++it) destroy_cstring(it);
    
            // Deallocate the array of arrays of chars
            destroy_cvector_string(&cv);
    
        }
    
    }
    

    错误:

    1. 您正在为字符数组释放分配的内存,然后读入该内存。

    解除分配

     for (int i{}; i < n; i++)
                    free(p[i]);
    

    使用

     for (int i{}; i < n; i++) {
                scanf("%s", p[i]);
                z += strlen(p[i]);
            }
    
    1. 你必须为指针分配内存,而不是为字符分配内存。

      p = (char**)malloc(sizeof(char) * n);
      

    【讨论】:

    • 非常感谢!!!
    • 不客气^^
    • 好吧,所以基本上我虽然如果我使用免费我只是删除已经读取的元素而不是释放内存,对不起。
    • struct cvector_stringstruct cstring 正在用 C++ 语言混淆 C 语言,在大型程序中很难调试和理解,但至少你没有 typedef 他们。
    • 我认为通过将struct cstring 设置为char * 可以大大缩短这段代码,因为您似乎没有在任何地方使用size。 (对不起,如果我听起来很消极。)
    【解决方案4】:

    作为答案的补充,您需要在程序属性选项中更改选择什么是语言 C/C++

    【讨论】:

    • 谢谢,我确实更改了编译器,但我有同样的问题,检测到堆损坏。
    • 这是为了避免 malloc 的强制转换
    猜你喜欢
    • 2013-07-30
    • 2015-09-08
    • 2016-05-08
    • 2023-03-11
    • 2011-05-31
    • 1970-01-01
    相关资源
    最近更新 更多