【问题标题】:C - realloc() pointer then set value inside functionC - realloc() 指针然后在函数内设置值
【发布时间】:2017-10-02 11:38:13
【问题描述】:

我正在尝试用 C 编写一个函数,将文件读入传递给它的 char 数组。

void read_file(char* path, char** bufptr, char* buffer){
  /* open the file, and exit on errors */
  FILE *fp = fopen(path, "r");
  if(fp == NULL){
    perror("Failed to open file");
    exit(1);
  }
  /* figure out how long the file is to allocate that memory */
  fseek(fp, 0, SEEK_END);
  long length = ftell(fp);
  rewind(fp);
  /* allocate memory */
  *bufptr = realloc(*bufptr, length+1);
  fread(buffer, length, 1, fp);
  buffer[length] = 0;
}

我的想法是我会像这样使用它:

int main(int argc, char** argv){
  char* somestring = malloc(1024);
  core_read_file("/some/file/path", &somestring, somestring);
  printf("In main(): %s\n", somestring);
  free(somestring);
  return 0;
}

但是,每当我使用它时,当程序编译时,printf 不会向控制台打印任何内容。我刚开始并在非常基本的程度上理解“间接”的概念,但是有人可以向我解释为什么我的代码不能按我期望的方式工作,以及我应该如何实现这个函数。

(这不是家庭作业,因此任何可行的解决方案或方法都是完美的)

【问题讨论】:

  • 我认为您不需要 read_filebuffer 参数。只需在您当前正在写 buffer 的任何地方写 *bufptr,例如fread(*bufptr, ...); (*bufptr)[length] = 0
  • 您应该使用rb 模式打开文件。还有通常的“你正在覆盖realloc 中的旧指针”投诉......
  • 不是realloc,你可以malloc最初的正确数量并返回吗?
  • 如果 realloc 将数据移动到一个新地址,那么 buffer 指向一个无效地址(不再分配的内存)。
  • 您还检查了您正在调用的函数(如 malloc、realoc、fread)和您的 core_read_file 函数的返回值,而不是 void - 如果出现问题,请返回读取错误的字节数跨度>

标签: c realloc


【解决方案1】:

read_file 的最后两行应该是:

  fread(*bufptr, length, 1, fp);
  (*bufptr)[length] = 0;

新分配的缓冲区中的指针在*bufptr,而不是buffer

但是你的程序过于复杂,不需要传递三个参数就可以做到read_file。两个就够了,像这样:

void read_file(char* path, char** bufptr) {
  /* open the file, and exit on errors */
  FILE *fp = fopen(path, "r");
  if (fp == NULL) {
    perror("Failed to open file");
    exit(1);
  }
  /* figure out how long the file is to allocate that memory */
  fseek(fp, 0, SEEK_END);
  long length = ftell(fp);
  rewind(fp);
  /* allocate memory */
  *bufptr = realloc(*bufptr, length + 1);
  fread(*bufptr, length, 1, fp);
  (*bufptr)[length] = 0;
}    

int main(int argc, char** argv) {
  char* somestring = malloc(1024);  //  char* somestring = NULL would be even better here
  read_file("readme.txt", &somestring);
  printf("In main(): %s\n", somestring);
  free(somestring);
  return 0;
}

为简洁起见,这里仍然没有对realloc 进行错误检查。

【讨论】:

    【解决方案2】:

    如果您要在函数内部分配内存 - 无需在外部分配。但是应该有记录的协议 - 在失败的情况下 - 没有任何东西未释放,在成功的情况下 - 调用函数负责释放缓冲区指针。

    您的读取功能必须进行更多的错误检查,并且还必须关闭任何分支上的文件。

    这是读取的示例代码:

    #define _CRT_SECURE_NO_WARNINGS
    
    #include <stdio.h>
    #include <stdlib.h>
    
    long read_file(const char* path, char** bufptr) {
        char* buffer;
        int res;
        size_t read;
        FILE *fp;
        if (path == NULL || bufptr == NULL) {
            perror("Invalid parameters");
            return -6;
        }
        /* open the file, and exit on errors */
        fp = fopen(path, "rb");
        if (fp == NULL) {
            perror("Failed to open file");
            return -1;
        }
        /* figure out how long the file is to allocate that memory */
        res = fseek(fp, 0, SEEK_END);
        if (res != 0) {
            perror("Failed to seek file");
            fclose(fp);
            return -2;
        }
        long length = ftell(fp);
        if (length <= 0) {
            perror("Failed ftell");
            fclose(fp);
            return -3;
        }
        rewind(fp);
        /* allocate memory */
        buffer = malloc(length + 1);
        if (buffer == NULL) {
            perror("Out of memory");
            fclose(fp);
            return -4;
        }
        read = fread(buffer, 1, length, fp);
        fclose(fp);
    
        if ((long)read != length) {
            perror("Failed to read whole file");
            free(buffer);
            return -5;
        }
        buffer[length] = 0;
        *bufptr = buffer;
        return length;
    }
    int main() {
        char* somestring;
        long res = read_file("c:/key.txt", &somestring);
        if (res < 0) {
            //nothing is leaked - everything opened or allocated was closed and freed by the function
            exit(res);
        }
        printf("In main(): %s\n", somestring);
        free(somestring);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-09-17
      • 1970-01-01
      • 2015-07-13
      • 2012-03-13
      • 1970-01-01
      • 2012-03-15
      • 2013-10-31
      • 2017-05-29
      • 2021-04-18
      相关资源
      最近更新 更多