Chinaunix

标题: 帮忙看看这个getLine函数 [打印本页]

作者: iwinux    时间: 2006-08-02 10:06
标题: 帮忙看看这个getLine函数
因为刚刚学 C 语言,经常做练习的时候都需要用到getchar()之类的函数,为了方便,我参考《C语言的科学和艺术》这本书的代码,实现了一个getLine函数,这里我把代码贴出来,大家帮忙看看有什么bug,谢谢!



  1. #define BUFSIZE 255
  2. /*reference:The Art and Science of C*/
  3. int getLine(char ** line) {
  4.         char * tmp;
  5.         int c, n = 0, size = BUFSIZE;

  6.         if (*line) {
  7.                 free(*line);
  8.         }

  9.         *line  = (char *) malloc(size + 1);

  10.         if (!*line) {
  11.                 return 0;
  12.         }

  13.         while ((c = getchar()) != '\n' && c != EOF) {
  14.                 if (n == size) {
  15.                         size *= 2;
  16.                         tmp = (char *) malloc(size + 1);
  17.                         strncpy(tmp, *line, n);
  18.                         free(*line);
  19.                         *line = tmp;
  20.                 }
  21.                 *(*line + n) = c;
  22.                 n++;
  23.         }

  24.         if (n == 0 && c == EOF) {
  25.                 free(*line);
  26.                 return 0;
  27.         }
  28.        
  29.         *(*line + n)= '\0';
  30.         tmp = 0;

  31.         return n;
  32. }
复制代码

作者: flw10000    时间: 2006-08-02 11:11
原帖由 iwinux 于 2006-8-2 10:06 发表
因为刚刚学 C 语言,经常做练习的时候都需要用到getchar()之类的函数,为了方便,我参考《C语言的科学和艺术》这本书的代码,实现了一个getLine函数,这里我把代码贴出来,大家帮忙看看有什么bug,谢谢!


        if (*line) {
                free(*line);
        }
[c ...



这里还没有malloc就free,会有问题吧!
作者: flw10000    时间: 2006-08-02 11:18
明白你的意思了

如果调用时已经malloc了,要先free,重新malloc,因为没法知道调用者malloc了多大空间!
作者: MackedNice    时间: 2006-08-02 12:58
if (*line) {
                free(*line);
        }
有问题. line 只是一个指针的地址。这个指针所指的内存是分配在函数栈上还是分配在堆上或者可能这个指针什么也没有指向,
你都是不知道的。所以你这样做是错误的。
当然你可以判断一下指针的地址是不是有效
if(line == NULL)
     return -1;


其他的好象没有问题。写得不错。
-------------------------------------
我学c的时候还写不出这样代码。
作者: Bayweb    时间: 2006-08-02 13:00
原帖由 flw10000 于 2006-8-2 11:18 发表
明白你的意思了

如果调用时已经malloc了,要先free,重新malloc,因为没法知道调用者malloc了多大空间!

>>
>>
>>一般malloc之前都会检查一下是否为空,或者size是否为零。如果不是十分必要,
>>在函数的结尾务必free一下。
>>
>>
作者: flw10000    时间: 2006-08-02 18:03
原帖由 Bayweb 于 2006-8-2 13:00 发表

>>
>>
>>一般malloc之前都会检查一下是否为空,或者size是否为零。如果不是十分必要,
>>在函数的结尾务必free一下。
>>
>>


咋俩的说法并不矛盾

我说的是楼主在程序开始处就判断*line如果为真就free,可能考虑的是并不知道该函数的调用者为*line申请了多大空间,所以free了,重新malloc了(size + 1)个内存空间!
作者: 默难    时间: 2006-08-02 18:26
LZ看以下几个函数:
fgets realloc
作者: yuxh    时间: 2006-08-02 18:29
没有大的问题.
但在最后

  1.         if (n == 0 && c == EOF) {
  2.                 free(*line);
  3.                 return 0;
  4.         }
复制代码

如果不加上一句*line = NULL;的话,再次调入函数会重复free,程序会core哦.
作者: flw    时间: 2006-08-02 18:36
man 3 getline
man 3 fgets
man 3 realloc
作者: iwinux    时间: 2006-08-02 21:45
Google 了一下
这篇文章说realloc有潜在的隐患
http://www.csdn.net/develop/article/27/27950.shtm

不过C-FAQ又说:
Since you always want each block of dynamically-allocated memory to be contiguous (so that you can treat it as if it were an array), you and realloc have to worry about the case where realloc can't make the old block of memory bigger ``in place,'' but rather has to relocate it elsewhere in order to find enough contiguous space for the new requested size. realloc does this by returning a new pointer. If realloc was able to make the old block of memory bigger, it returns the same pointer. If realloc has to go elsewhere to get enough contiguous memory, it returns a pointer to the new memory, after copying your old data there. (In this case, after it makes the copy, it frees the old block.) Finally, if realloc can't find enough memory to satisfy the new request at all, it returns a null pointer. Therefore, you usually don't want to overwrite your old pointer with realloc's return value until you've tested it to make sure it's not a null pointer. You might use code like this:


看起来很安全 -____-

[ 本帖最后由 iwinux 于 2006-8-2 21:57 编辑 ]
作者: iwinux    时间: 2006-08-02 22:46
修改后的代码


  1. /*reference:The Art and Science of C*/
  2. int readLine(FILE * infile, char ** line) {
  3.         char * tmp, *test;
  4.         int c, n = 0, size = BUFSIZE;

  5.         if (*line) {
  6.                 free(*line);
  7.         }

  8.         *line  = (char *) malloc(size + 1);

  9.         if (!*line) {
  10.                 return 0;
  11.         }

  12.         while ((c = fgetc(infile)) != '\n' && c != EOF) {
  13.                 if (n == size) {
  14.                         size *= 2;
  15.                         //tmp = (char *) malloc(size + 1);
  16.                         tmp = (char *) realloc(*line, size + 1);
  17.                        
  18.                         if (!tmp) {
  19.                                 //line = 0;
  20.                                 //return 0;
  21.                                 return n;
  22.                         }
  23.                        
  24.                         //strncpy(tmp, *line, n);
  25.                         //free(*line);
  26.                         test = *line;
  27.                         *line = tmp;
  28.                 }
  29.                 *(*line + n) = c;
  30.                 n++;
  31.         }

  32.         if (n == 0 && c == EOF) {
  33.                 *line = NULL;
  34.                 free(*line);
  35.                 return 0;
  36.         }
  37.        
  38.         *(*line + n)= '\0';
  39.         tmp = 0;

  40.         return n;
  41. }
复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2