int8_t** FileToColorMap(char* colorfile, int* colorcount)
{
FILE* fp = fopen (colorfile, "r");
if (fp==NULL)
{
printf("no such file.");
return 0;
}
int r,g,b;
fscanf(fp, "%d", colorcount);
uint8_t* output;
output = (uint8_t *)malloc(*colorcount * sizeof(uint8_t));
for (int i = 0; i < *colorcount;i++) {
if( fscanf(fp, "%d %d %d", &r, &g, &b) != EOF ) {
// int* arr= (int *)malloc(3 * sizeof(int));
// arr[0] = r;
// arr[1] = g;
// arr[2] = b;
int arr[3] = {r,g,b};
output[i] = *arr;
} else
{
freeMap(i+1, &output);
return NULL;
}
}
fclose(fp);
return *output;
}
这会导致seg错误,或者错误1或其他什么,即使当我尝试返回输出,**输出,&输出。
看起来你的帖子大部分都是代码;请添加更多详细信息。
有很多问题:
- 类型和分配错误
uint8_t* output;
output = (uint8_t *)malloc(*colorcount * sizeof(uint8_t));
您需要在此处声明指针到指针,并为非uint8_t 的指针分配空间
两个数组的类型都不正确。arr
是自动变量,在函数范围外取消引用它是UB
- 许多其他问题
int8_t** FileToColorMap(char* colorfile, int* colorcount)
{
FILE* fp = fopen (colorfile, "r");
if (fp==NULL)
{
printf("no such file.");
return 0;
}
int8_t r,g,b;
if(fscanf(fp, "%d", colorcount) != 1)
{
/* fscanf failed - do something */
}
int8_t **output = malloc(*colorcount * sizeof(*output));
for (int i = 0; i < *colorcount;i++) {
if( fscanf(fp, "%hhx %hhx %hhx", &r, &g, &b) == 3) {
uint8_t *arr = malloc(3 * sizeof(*arr));
arr[0] = r;
arr[1] = g;
arr[2] = b;
output[i] = arr;
} else
{
freeMap(i+1, &output);
return NULL;
}
}
fclose(fp);
return output;
}
如果malloc,请始终检查结果。为了清楚起见,我没有
总的来说,代码是不必要的复杂。我建议使用结构,因为在这种情况下,最内部的维度总是3项宽。
假设color_count
由调用者分配并返回读取的项目数,则:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef struct
{
uint8_t r;
uint8_t g;
uint8_t b;
} rgb_t;
rgb_t* FileToColorMap (const char* color_file, int* color_count)
{
FILE* fp = fopen (color_file, "r");
if (fp==NULL)
{
*color_count = 0;
return NULL;
}
int count;
if(fscanf(fp, "%d", &count) != 1)
{
fclose(fp);
*color_count = 0;
return NULL;
}
rgb_t* result = malloc ( sizeof(rgb_t[count]) );
if(result == NULL)
{
fclose(fp);
*color_count = 0;
return NULL;
}
for (int i = 0; i<count; i++)
{
int r,g,b;
if( fscanf(fp, "%d %d %d", &r, &g, &b) != 3 )
{
free(result);
fclose(fp);
*color_count = 0;
return NULL;
}
result[i].r = r;
result[i].b = b;
result[i].g = g;
}
fclose(fp);
*color_count = count;
return result;
}
注:
- 添加到文件名参数的常量正确性
- 正确清理动态内存和文件处理错误
- 使用临时内部变量
count
,直到您知道一切顺利为止。在函数末尾写入调用方的变量 - 检查
fscanf
的结果是否符合预期的项目数,而不仅仅是它不是EOF
高级:
要进一步清理代码,需要查看错误处理和资源清理。上面代码中的错误处理有很多重复,这并不理想-清理应该集中在一个位置,否则很容易发生资源泄漏,特别是在以后的维护过程中
有三种方法可以做到这一点:清理宏;关于错误goto";模式或包装器函数。我更喜欢后者,因为它最不乱。这是通过将资源的所有权分解为外部函数来完成的,该函数是调用者所知道的。然后将实际的算法放入内部static
函数中。
这里有一个例子,使用集中清理/错误处理:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct
{
uint8_t r;
uint8_t g;
uint8_t b;
} rgb_t;
static bool FileReadColorMap (FILE* fp, rgb_t** result, int* color_count)
{
int count;
fscanf(fp, "%d", &count);
*result = malloc ( sizeof(rgb_t[count]) );
if(*result == NULL)
{
return false;
}
for (int i = 0; i < count; i++)
{
int r,g,b;
if( fscanf(fp, "%d %d %d", &r, &g, &b) != 3 )
{
return false;
}
(*result)[i].r = r;
(*result)[i].b = b;
(*result)[i].g = g;
}
*color_count = count;
return true;
}
rgb_t* FileToColorMap (const char* color_file, int* color_count)
{
rgb_t* result = NULL;
FILE* fp = NULL;
fp = fopen (color_file, "r");
if(fp == NULL)
{
*color_count = 0;
return NULL;
}
if(!FileReadColorMap(fp, &result, color_count))
{
*color_count = 0;
free(result); // it is safe to do free(NULL)
result = NULL; // return NULL
}
fclose(fp); // always called
return result;
}