提问人:Vinicius Caetano 提问时间:6/21/2023 最后编辑:Vinicius Caetano 更新时间:6/23/2023 访问量:85
当我尝试在结构中释放 2d 矩阵时,程序退出没有任何错误
Program exits without any error when I try to free a 2d matrix in a struct
问:
我使用包含空格分隔的数字的文件的解析器在我的结构中创建并填充我的无符号字符的 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);
}
我可以编译并运行它而不会出现任何错误。 该程序似乎是随机工作的,因为有时它会正确释放,而有时程序只是在没有任何解释的情况下停止。
答:
1赞
Leon Kacowicz
6/21/2023
#1
这些行似乎有问题:
char buf[] = "";
fgets(buf, MAX_LEN, ptr);
buf
应该指向一个至少很长的数组,因为可能会写入多达 MAX_LEN 个字节。MAX_LEN
fgets
ptr
我建议在调用之前使用 将 MAX_LEN 个字节分配给malloc
buf
fgets(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 才能读取空行。当你试着像现在这样读一个空行时,因为你撒谎并说有空间,你会导致未定义的行为。buf
char[1]
1
char
fgets
10000
1
0
fgets
\n
buf
char[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
缓冲区太小
备选方案示例:
// 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 来使用它们,这导致我的程序随机中断。
评论
struct imagem imagem = malloc(sizeof(struct imagem));
struct imagem imagem = malloc(sizeof(struct imagem))
-- 除非是 ,否则这不是 C++ 代码。在 C++ 中,如果不强制转换为指针类型,这将无法编译(除非再次,分配给的类型是 )。imagem
void *
malloc
void *
-Wall -Wextra -pedantic-errors -g -fsanitize=address,undefined