c中的字符串文字

时间:2015-08-20 06:05:14

标签: c arrays c-strings

我在C和字符数组方面遇到了一些麻烦。我尝试搜索SO,但我没有看到任何可以帮助我的东西,或者我没有找到正确的东西。

我有这个功能:

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!

我知道如果我在函数内没有malloc,那么内存就会超出范围,这样就不行了,但是按原样使用当前函数,我就崩溃了。我做错了什么?

修改 执行此读取文件后

在上面的readFile函数之后我进入了这个函数

GLuint getShaderProgram(const char* vshad, const char* fshad)
{
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

    glShaderSource(vertexShader, 1, &vshad, NULL);
    glCompileShader(vertexShader);

    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

    if(!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        printf("ERROR VERTEX COMPILATION_FAILED %s\n",infoLog);
        SDL_Quit();
    }

    GLuint fragmentShader  = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fshad, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);

    if(!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        printf("ERROR FRAGMENT COMPILATION_FAILED %s\n",infoLog);
        SDL_Quit();
    }

    GLuint shaderProgram = glCreateProgram();

    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        printf("ERROR SHADER PROGRAM COMPILATION_FAILED %s\n",infoLog);
        SDL_Quit();
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return shaderProgram;
}

所以完整的代码路径就像这样

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

sp = getShaderProgram(vv, ff);

free(vv);
free(ff);

我在free(..)崩溃,删除那些并且程序运行正常,但我觉得它是内存泄漏。

3 个答案:

答案 0 :(得分:3)

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

请更改以下行:

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

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

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

当您将值读入char而不是int时:

  1. 如果char为unsigned,那么您将获得无限循环,因为我们永远不会EOF
  2. 如果char为signed,那么0xFF(即ÿ被接受为EOF)会被视为EOF,会产生错误的结果。
  3.   

    另外,检查功能是否按预期工作:

    • 检查文件打开是否成功。     FILE * fp = fopen(file_path,&#34; r&#34;);     if(fp!= NULL){       //做东西     }
    • 检查内存是否已分配

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

答案 1 :(得分:2)

在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)的缓冲区 - 如果由于某种原因您没有严格的内存限制或大量文件。

答案 2 :(得分:1)

line = realloc(line, (sizeof(char) * index));更改为

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

您正尝试将line重新分配到index大小,然后尝试在line[index]中存储'\ 0'字符,这是未定义的行为。