c语言中的字符串文字

c语言中的字符串文字,c,arrays,c-strings,C,Arrays,C Strings,我在C和字符数组方面遇到了一些问题。我试图继续搜索,但是我没有看到任何对我有帮助的东西,或者我没有找到合适的东西 我有一个函数: char* readFile(char* file_path) { FILE* fp = fopen(file_path, "r"); size_t buffer = 4096; char ch; int index = 0; char* line = (char*)malloc(sizeof(char) * buffer); while( (

我在
C
和字符数组方面遇到了一些问题。我试图继续搜索,但是我没有看到任何对我有帮助的东西,或者我没有找到合适的东西

我有一个函数:

char* readFile(char* file_path)
{
  FILE* fp = fopen(file_path, "r");
  size_t buffer = 4096;
  char ch;
  int index = 0;
  char* line = (char*)malloc(sizeof(char) * buffer);
  while( (ch = (char)fgetc(fp)) != EOF )
  {
      line[index] = ch;
      ++index;
      if(index == buffer -1)
      {
          buffer = buffer * 2;
          line = realloc(line, buffer);
      }
  }
  line = realloc(line, (sizeof(char) * index));
  line[index] = '\0';
  fclose(fp);
  return line;
}
现在,当我在代码中使用这个函数并试图释放引用时,它会导致崩溃,所以我认为我在某处泄漏内存

char* data;

data = readFile("....");
free(data) <-- this line causes a crash!
所以完整的代码路径是这样的

char* vv = readFile("vshad.vs");
char* ff = readFile("fshad.fs");

sp = getShaderProgram(vv, ff);

free(vv);
free(ff);

我在空闲时(..)会崩溃,删除这些崩溃,程序运行正常,但我觉得这是内存泄漏。

change
line=realloc(line,(sizeof(char)*index))

line = realloc(line, (sizeof(char) * (index+1)));

您正在尝试将
重新定位到
索引
大小,并在
行[index]
中存储“\0”字符,这是未定义的行为。

更改
行=重新定位(行,(sizeof(char)*index))

line = realloc(line, (sizeof(char) * (index+1)));

您正在尝试将
重新定位到
索引
大小,并且下一个语句试图在
行[index]
中存储'\0'字符,这是未定义的行为。

为数组分配的内存不足。您刚刚为字符数组分配了内存,但没有为终止的
\0
字符分配内存。这会导致未定义的行为

请更改以下行:

line = realloc(line, (sizeof(char) * index));

另外,将
ch
的数据类型从
char
更改为int,因为
fgetc()
的返回类型是
int
(而不是
char
)。建议将返回值分配给整型变量

将值读入
char
而不是
int
时:

  • 如果char是
    无符号的
    ,那么您将得到一个无限循环,因为我们永远不会得到
    EOF
  • 如果字符是
    有符号的
    ,则
    0xFF
    (即
    ÿ
    被接受为EOF)被视为产生错误结果的
    EOF
  • 此外,检查功能是否按预期工作:

    • 检查文件打开是否成功。 FILE*fp=fopen(文件路径,“r”); 如果(fp!=NULL){ //做事 }
    • 检查是否分配了内存

      char* tmpLine = realloc(line, (sizeof(char) * (index+1)));
      if (tmpLine != NULL)
      {
        line = tmp;
        line[index] = '\0';
      }
      else
      {
        //Handle insufficient memory
      }
      

    为阵列分配的内存不足。您刚刚为字符数组分配了内存,但没有为终止的
    \0
    字符分配内存。这会导致未定义的行为

    请更改以下行:

    line = realloc(line, (sizeof(char) * index));
    

    另外,将
    ch
    的数据类型从
    char
    更改为int,因为
    fgetc()
    的返回类型是
    int
    (而不是
    char
    )。建议将返回值分配给整型变量

    将值读入
    char
    而不是
    int
    时:

  • 如果char是
    无符号的
    ,那么您将得到一个无限循环,因为我们永远不会得到
    EOF
  • 如果字符是
    有符号的
    ,则
    0xFF
    (即
    ÿ
    被接受为EOF)被视为产生错误结果的
    EOF
  • 此外,检查功能是否按预期工作:

    • 检查文件打开是否成功。 FILE*fp=fopen(文件路径,“r”); 如果(fp!=NULL){ //做事 }
    • 检查是否分配了内存

      char* tmpLine = realloc(line, (sizeof(char) * (index+1)));
      if (tmpLine != NULL)
      {
        line = tmp;
        line[index] = '\0';
      }
      else
      {
        //Handle insufficient memory
      }
      

    在C语言中,检查具有返回值的函数的返回值非常重要。在您的情况下,您使用realloc,但不必检查返回值

    char* tmp = realloc(line, newbuffersize);
    if (tmp != NULL)
    {
      line = tmp;
    }
    else
    {
      abort();
    }
    
    您应该检查文件是否正确打开,如果打开失败,并且在调用中开始使用空指针,您将得到有趣的行为

    离开while循环后,使用新的realloc缩小缓冲区。这很好,但您需要为结尾添加空间\0:

    char* tmp = realloc(line, index + 1);
    if (tmp != NULL)
    {
      line = tmp;
      line[index] = '\0';
    }
    

    一般来说,在执行分配时有点无效,如果先检查文件的大小(例如,先查看fseek到结尾,然后执行ftell,然后执行fseek到开始),然后分配相同大小的缓冲区(+1),则会更有效在阅读之前-如果你不是因为某种原因有严格的内存限制或一个大文件。

    在C语言中,检查具有返回值的函数的返回值是很重要的。在您的情况下,您使用realloc,但不必检查返回值

    char* tmp = realloc(line, newbuffersize);
    if (tmp != NULL)
    {
      line = tmp;
    }
    else
    {
      abort();
    }
    
    您应该检查文件是否正确打开,如果打开失败,并且在调用中开始使用空指针,您将得到有趣的行为

    离开while循环后,使用新的realloc缩小缓冲区。这很好,但您需要为结尾添加空间\0:

    char* tmp = realloc(line, index + 1);
    if (tmp != NULL)
    {
      line = tmp;
      line[index] = '\0';
    }
    

    一般来说,在执行分配时有点无效,如果先检查文件的大小(例如,先查看fseek到结尾,然后执行ftell,然后执行fseek到开始),然后分配相同大小的缓冲区(+1),则会更有效阅读前-如果不是因为某种原因,你有严格的内存限制或一个大文件。

    ch
    应该是
    int
    ,而不是
    char
    ,因为这是
    fgets
    的返回值,允许它区分常规输入和
    EOF
    。收缩字符串时,应分配
    index+1
    字节,额外的字节用于空终止符。您的最终
    realloc()
    大小太小了一个。。。您需要
    index+1
    字节,以便
    line[index]
    仍在空字符的范围内。
    sizeof(char)
    根据定义等于
    1
    。所有这些强制转换都是无用的,而对于
    fgets()
    的强制转换更是隐藏了一个严重的编程错误,正如M Oehm在这篇评论中指出的那样:如果内部控制数据被覆盖,则
    free
    可能会崩溃。你在
    readFile
    和“free”之间做什么?你考虑过在Valgrind这样的内存检查器中运行这个程序吗?@MOehm,谢谢,我会做出这些更改。我使用readFile函数来加载glsl