【问题标题】:Free array returned from function从函数返回的空闲数组
【发布时间】:2017-09-20 17:36:06
【问题描述】:

抱歉,如果这出现在其他地方,我无法找到明确的答案。 我一直在使用 Ed S 的答案,选项 1(链接如下)来分配内存,填充数组,然后将其返回给调用者。 他建议在你完成后释放内存,但是当我添加 free() 行时,我得到一个核心转储。 我曾在 GDB 上玩过,但我的技能可能不是我需要的。

提前感谢您提供的任何帮助。

回答链接:Returning an array using C

代码:

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

char * createArray();

int main(int argc, char *argv[]){
    printf("Creating Array...\n");
    // pointer to an int
    char *p;
    // size of the array
    int i,j;
    // width of array
    int width = 7;
    // height of array
    int height = 5;
    // get an array from the function
    p = createArray(width, height);
    // check if p was created properly
    if (p){
        // print out the array
        for (i = 0; i < width; ++i){
            for (j = 0; j < height; ++j){
                printf("[%c] ", *(p + (i * width) + j)); 
            }
        printf("\n");
        }

        // here's where it hits the fan
        free(p);
    }
    return 0;
}

char * createArray(int w, int h){
    // allocate some memory for the array
    char *r = malloc(w * h * sizeof(char));
    // check if the memory allocation was successful
    if(!r){
        return NULL;
    }
    int i, j;
    int count = 0;
    for (i = 0; i < w; ++i){
        for (j = 0; j < h; ++j){
            *(r + (i * w) + j) = 'X';
            ++count;
        }
    }
    return r;
}

【问题讨论】:

  • 您在Valgrind 工作的平台上吗?如果是这样,请使用它。核心转储可能意味着您已超出分配数组的范围。
  • 为什么人们(尤其是新手,我注意到了)喜欢*(r + (i * w) + j) 而不是r[i * w + j]?为什么嵌套循环计数?你从不使用计数。您是要创建字符串吗?您在任何地方都没有空终止符,因此您创建字符串,只是创建字符数组,
  • @JonathanLeffler - 我现在会检查 valgrind,我没有做太多调试,但它是学习的重要工具,所以现在是最好的时机! - 不确定,我只是使用它,因为这就是我学会做它的方式。 - 最后,计数在那里,因为我最初让数组包含整数,我想检查我是否正确创建了数组,所以每个元素都有一个单独的值。当我将其更改为字符时,我只是忘记删除计数。
  • 这个*(r + (i * w) + j) = 'X'应该是*(r + (i * h) + j) = 'X'
  • main也有类似的错误:表达式*(p + (i * width) + j)应该是*(p + (i * height) + j)

标签: c arrays malloc free


【解决方案1】:

有了这个

char *r = malloc(w * h * sizeof(char));

您分配了w * h(7 * 5 = 35 字节)的内存。但是

        *(r + (i * w) + j) = 'X';

可以访问远远超出您分配的 35 个字节(您将查看是否在循环中测试 i * w + j 的可能值),从而导致未定义的行为。

这可能会覆盖 malloc 的内部数据结构,因此您在 free() 时碰巧得到核心转储。

【讨论】:

  • 是的,Valgrind 证实了这一诊断。在打印循环中main()也有相应的问题。
  • 感谢您的回复!我现在将接受@JonathanLeffler 的建议并尝试学习 valgrind。谢谢!
  • @dleft:使用 Valgrind 时要记住的主要事情是使用 -g 选项编译 链接,因此您会被告知发生问题的行号。
  • @JonathanLeffler 感谢您的建议!现在浏览 Valgrind 的文档。当我研究了如何修复代码后,我将在问题的底部发布解决方案。
【解决方案2】:

你在这些方面犯了一个错误

*(r + (i * w) + j) = 'X';

printf("[%c] ", *(p + (i * width) + j));

要保持在“2D”数组的边界内——它是一维的,但你正在像编译器一样处理它——它应该在那里是i * length

*(r + (i * h) + j) = 'X';`

printf("[%c] ", *(p + (i * height) + j)); `

如果你使用它,你应该能够保持在边界内而不会弄得一团糟。

【讨论】:

  • 感谢您的提示!我现在已经启动并运行了,但在继续此之前,我真的应该在遍历 2D 数组方面做更多的工作!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 2016-10-13
相关资源
最近更新 更多