【问题标题】:uint8_t array return is causing errors using all scenarios (**, *, &, nothing)uint8_t 数组返回在所有情况下都会导致错误(**、*、&,什么都没有)
【发布时间】:2020-12-27 13:03:37
【问题描述】:
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;
}

即使我尝试返回输出、**输出和 &ouput,这也会导致 seg 错误错误或错误 1 ​​或其他错误。

看起来您的帖子主要是代码;请添加更多详细信息。

【问题讨论】:

  • 输出 --> 从不兼容的指针类型返回
  • *output --> 从结果类型为“uint8_t **”(又名“unsigned char **”)的函数返回“uint8_t *”(又名“unsigned char *”)的不兼容指针类型;用 & [-Wincompatible-pointer-types] 获取地址
  • No seg error with &output 但中止陷阱 6 和 --> 警告:与局部变量“输出”相关的堆栈内存地址返回 [-Wreturn-stack-address]
  • edit您的问题添加更多详细信息。所有信息都应该在问题中,而不是分散在 cmets 中。 cmets 用于提供建议或要求澄清。请写出你想用这个函数实现什么,并展示调用这个函数的代码,包括参数的定义和返回值的变量。
  • 我想目的是返回一个*colorcount RGB值的数组,即一个结构数组或一个二维数组。请在问题中澄清这一点

标签: c pointers memory-address uint8t


【解决方案1】:

有很多问题:

  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,请始终检查结果。我不是为了清楚起见

【讨论】:

  • Nitpick:应该检查来自 fscanf(fp, "%d", colorcount); 的返回值,但除此之外,我认为这可能是 OP 正在寻找的。​​span>
【解决方案2】:

总体而言,代码是不必要的复杂。我建议改用结构,因为在这种情况下,最里面的维度总是 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;
}

注意:

  • 为文件名参数添加了 const 正确性。
  • 发生错误时正确清理动态内存和文件句柄。
  • 使用临时内部变量count,直到您知道一切顺利。在函数末尾写入调用者的变量。
  • 检查 fscanf 的结果是否与预期的项目数相对应,而不仅仅是它不是 EOF。

高级:

要进一步清理代码,需要查看错误处理和资源清理。上面代码中的错误处理有很多重复,这并不理想 - 清理应该集中在一个位置,否则很容易导致资源泄漏,尤其是在以后的维护期间。

有三种方法可以做到这一点:清理宏、“on error 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多