当我尝试在结构中释放 2d 矩阵时,程序退出没有任何错误

Program exits without any error when I try to free a 2d matrix in a struct

提问人:Vinicius Caetano 提问时间:6/21/2023 最后编辑:Vinicius Caetano 更新时间:6/23/2023 访问量:85

问:

我使用包含空格分隔的数字的文件的解析器在我的结构中创建并填充我的无符号字符的 2d 数组

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


struct imagem{
    unsigned char ** matrix;
    char* file_path;
    int height;
    int width;
    int max_cinza;
    int histograma[256];
    char* location;
};

struct imagem* lerImagem(char file_path[])
{

    struct imagem* imagem = malloc(sizeof(struct imagem)); 
    imagem->file_path = file_path;
    FILE* ptr;
    ptr = fopen(file_path, "r");
    
    if (NULL == ptr) {
        printf("A imagem não está no file_path selecionado \n");
        imagem->height = 0;
        return imagem;
    }
    int MAX_LEN = 10000;
    char buf[] = "";

    fgets(buf, MAX_LEN, ptr); 
    char width[10], height[10];

    fscanf(ptr, "%s %s", width, height);

    int int_largura = atoi(width);
    int int_altura = atoi(height);
    imagem->height = int_altura;
    imagem->width = int_largura;


    imagem->matrix = (unsigned char**) malloc(imagem->height * sizeof(unsigned char*)); 
    for (int i = 0; i < int_altura; i++) {
        imagem->matrix[i] = (unsigned char*) malloc(imagem->width* sizeof(unsigned char)); 
    }
    

    
    fscanf(ptr, "%u", &imagem->max_cinza);

    for(int row = 0; row < imagem->height; row++){
        for(int column = 0; column < imagem->width; column++){
            fscanf(ptr, "%u ", &(imagem->matrix[row][column]));
            }
        }   

    fclose(ptr);

    return imagem;
}

void freeImagem(struct imagem* imagem_input){
    
    printf("iniciando free de matrix");
    
    for(int i=0; i < imagem_input->height; i++){
            free(imagem_input->matrix[i]);
    }
    free(imagem_input->matrix);
    
    free(imagem_input);
}

我可以编译并运行它而不会出现任何错误。 该程序似乎是随机工作的,因为有时它会正确释放,而有时程序只是在没有任何解释的情况下停止。

C GCC Malloc 免费

评论

1赞 273K 6/21/2023
c - C 与 C++ 不同,如果没有特定原因,不应将其与 C++ 标签结合使用。
0赞 pmacfarlane 6/21/2023
这是您的实际代码吗?这编译了吗?这看起来不应该:。struct imagem imagem = malloc(sizeof(struct imagem));
0赞 PaulMcKenzie 6/21/2023
struct imagem imagem = malloc(sizeof(struct imagem))-- 除非是 ,否则这不是 C++ 代码。在 C++ 中,如果不强制转换为指针类型,这将无法编译(除非再次,分配给的类型是 )。imagemvoid *mallocvoid *
0赞 Vinicius Caetano 6/21/2023
这是错误的,我修复了标签
3赞 Ted Lyngmo 6/21/2023
@ViniciusCaetano 你意识到他们在你编辑问题之前质疑了代码的样子,对吧?这不应该让人感到惊讶,因为你改变了他们质疑的事情。无论如何,它仍然不是一个最小的可重复示例。我们无法运行它来重现问题。您可能还想添加一些编译器选项:都很好。编译后,修复警告,然后运行程序,看看是否收到某种错误报告。-Wall -Wextra -pedantic-errors -g -fsanitize=address,undefined

答:

1赞 Leon Kacowicz 6/21/2023 #1

这些行似乎有问题:

    char buf[] = "";
    fgets(buf, MAX_LEN, ptr); 

buf应该指向一个至少很长的数组,因为可能会写入多达 MAX_LEN 个字节。MAX_LENfgetsptr

我建议在调用之前使用 将 MAX_LEN 个字节分配给mallocbuffgets(buf, MAX_LEN, ptr)

编辑:在代码中,您只是将 10k 字节读取到 BUF 中,但之后您不再使用 BUF。您确定这是预期的行为吗?

评论

0赞 pmacfarlane 6/21/2023
我认为你的观察是有道理的。我不确定他们是否是答案。也许作为评论更好(除非您确信这将解决 OP 的问题)。
0赞 Leon Kacowicz 6/21/2023
@pmacfarlane我同意。我不确定这是否会解决问题,因为除了这个错误之外,可能还有其他错误。除此之外,提问者(尚未)提供此代码应该正确运行的文件示例。编辑:老实说,我相信修复此问题不会修复代码,因为读取(并抛出)文件的前 10k 字节似乎是一种非常奇怪的行为。我怀疑这几行应该被删除。
0赞 Vinicius Caetano 6/21/2023
我使用 fgets 跳过我正在解析的文件开头的空行。
0赞 Ted Lyngmo 6/21/2023
@ViniciusCaetano 是一个所以你有空间,但你说它有空间。请记住,null 终止符采用 ,这为字符留出了空间。 将尝试读取一行,包括 ,因此至少需要为 A 才能读取空行。当你试着像现在这样读一个空行时,因为你撒谎并说有空间,你会导致未定义的行为。bufchar[1]1charfgets1000010fgets\nbufchar[2]char[1]10000
0赞 Leon Kacowicz 6/22/2023
@ViniciusCaetano,如果第一行包含的字符数多于您在 buf 中分配的字符数,则会出现缓冲区溢出,这意味着 fgets 将写入 buf 未包含的内存位置。这意味着它可以覆盖其他变量的值,或者可能导致段错误(如果它尝试写入未分配给程序的内存位置)。如果你打算跳过一行,你可以参考这个:stackoverflow.com/questions/2799612/......
1赞 chux - Reinstate Monica 6/21/2023 #2

至少存在以下问题:

启用所有警告

这 4 行都使用启用良好的编译器发出警告:

imagem->height * sizeof(unsigned char*));
imagem->width * sizeof(unsigned char));
fscanf(ptr, "%u", &imagem->max_cinza);
fscanf(ptr, "%u ", &(imagem->matrix[row][column]));

格式不正确

"%u"匹配 a ,而不是 。unsigned * unsigned char *

struct imagem{
    unsigned char ** matrix;

    ...

    fscanf(ptr, "%u ", &(imagem->matrix[row][column]));  // Bad!

更好的是

fscanf(ptr, "%hhu ", &(imagem->matrix[row][column]));  // Better

删除不需要的并检查结果" "

if (fscanf(ptr, "%hhu", &(imagem->matrix[row][column])) != 1) {
  ; // Handle error
}  // Even better

缓冲区太小

@Leon Kacowicz

备选方案示例:

// int MAX_LEN = 10000;
// char buf[] = "";
// fgets(buf, MAX_LEN, ptr); 
#define MAX_LEN 10000
char buf[10000];
if (fgets(buf, sizeof buf, ptr) == NULL) {
  ; // Handle input error
}

使用 C 编译器

评论表明OP正在使用另一种语言(C++)来编译C代码。

改善分配

// imagem->matrix = (unsigned char**) malloc(imagem->height * sizeof(unsigned char*)); 

if (imagem->height < 0) {
  Handle_error(); // TBD code
}
imagem->matrix = malloc(sizeof imagem->matrix[0] * imagem->height); 
if (imagem->matrix == NULL && imagem->height) {
  Handle_error(); // TBD code
}

扫描时切勿使用不带宽度“%s”

char width[10], height[10];

// fscanf(ptr, "%s %s", width, height);
fscanf(ptr, "%9s %9s", width, height);

更好的是,扫描并检查结果。int

int int_largura, int_altura;
if (fscanf(ptr, "%s %s", &int_largura, &int_altura) != 2) {
  Handle_error();
}

混合 fscanf() 和 fgets() 是很棘手的

这通常会弄脏学习器代码。最好先只使用 fgets()'。

0赞 Vinicius Caetano 6/23/2023 #3

最后,问题出在file_path和位置属性上,因为我没有使用 malloc 来使用它们,这导致我的程序随机中断。

评论

0赞 Leon Kacowicz 6/25/2023
请记住,您刚才指出的问题在于您未包含在问题中的程序部分。除了其他评论者在您的代码中发现的许多错误外,您提到的这个错误可能会阻止您的程序工作,并且任何人都不可能发现,因为它不包含在问题中。下次您发布问题时,请包括程序的所有相关部分,以及它应该起作用的示例输入。请帮助其他人帮助你。
0赞 Community 6/25/2023
正如目前所写的那样,你的答案尚不清楚。请编辑以添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以在帮助中心找到有关如何写出好答案的更多信息。