【问题标题】:realloc(): invalid pointer error when using argc and argvrealloc():使用 argc 和 argv 时出现无效指针错误
【发布时间】:2018-04-09 19:28:14
【问题描述】:

作为练习的一部分,我正在用 C 语言开发一个类似 grep 的小程序,它应该接收一个字符串和一些文件名,以便在引用的文件中查找该字符串。

我通过硬编码文件名和字符串来实现它:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int searchString(char *str1, char *str2) {
    if (strstr(str1, str2) == NULL) {
        return 0;
    } else {
        return 1;
    }
}

void searchInFile(char *filename, char *str) {
    FILE *f;
    int lineno =0;
    size_t len;
    char *buffer;
    f = fopen(filename, "r");
    if (f != NULL) {
        while (getline(&buffer, &len, f) != -1) {
            lineno++;
            if (searchString(buffer, str)) {
                printf("[%s:%d] %s", filename, lineno, buffer);
            } 
        }
    }
    fclose(f);
}

int main() {
    searchInFile("loremipsum.txt", "dolor");
    return 0;
}

但只要我修改代码以更改 int main() 行以添加 argcargv,编译它然后运行它,脚本返回一个错误信息。 修改为:

int main(int argc, char *argv[]) {
    searchInFile("loremipsum.txt", "dolor");
    return 0;
}

收到的错误:

* `./a.out' 中的错误:realloc():无效指针:0x000056424999394d *

有人知道我为什么会收到这个错误吗?

【问题讨论】:

  • 是的,你永远不会为缓冲区分配内存,所以你的代码可能会做任何事情。
  • man 3 getline, ssize_t getline(char **lineptr, size_t *n, FILE *stream); "如果*lineptr设置为NULL并且*n在调用前设置0,那么getline()将分配一个缓冲区用于存储该行。" 此外,您应该在main() 中打开并验证f,然后将FILE* 参数传递给searchInFile 而不是char *
  • buffer 也没有设置为 NULL。
  • 我习惯了 Python 等更简单的语言,现在我的 C 语言有点生疏了。一旦我将缓冲区设置为 NULL 并将 len 设置为 0,代码就会再次运行。谢谢!关于在 main 中打开文件,练习为我们提供了函数原型,因此我需要接收文件名作为参数。
  • 当然。给我几分钟,我很乐意效劳。

标签: c realloc argv argc


【解决方案1】:

getline() 的主要问题是在将buffer 作为lineptr 参数和len 作为n 参数传递之前未能初始化len = 0;buffer = NULL;man 3 getline,解释:

ssize_t getline(char **lineptr, size_t *n, FILE *stream); 
...
If *lineptr is set to NULL and *n is set 0 before the call, then 
getline() will allocate a buffer for storing the line."

除非您初始化lineptr 的指针和n 的值,否则它们将包含不确定的(垃圾)值,这将阻止getline 自动正确处理分配。

修复这些问题,提供一些小的清理,并允许将文件名和搜索项作为第一个和第二个参数传递给您的程序,您可以执行类似于以下的操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* consider adding parameter for case-insensitive search */
int searchstring (const char *str1, const char *str2)
{
    if (strstr (str1, str2) == NULL)
        return 0;
    else
        return 1;
}

int searchinfile (const char *filename, char *str)
{
    int lineno = 0;
    size_t len = 0;
    char *buffer = NULL;
    FILE *f = fopen (filename, "r");

    if (!f) {   /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", filename);
        return 1;
    }

    /* read each line into buffer, search for searchstring */
    while (getline (&buffer, &len, f) != -1) {
        lineno++;
        if (searchstring (buffer, str))
            printf("[%s:%d] %s", filename, lineno, buffer);
    }
    fclose (f);     /* close file */

    return 0;
}

int main (int argc, char **argv) {

    if (argc < 3) { /* validate at least 2 arguments given */
        fprintf (stderr, "error: insufficient input.\n"
                "usage: %s <file> <searchstring>\n", argv[0]);
        return 1;
    }

    /* search file argv[1] for string argv[2] */
    if (searchinfile (argv[1], argv[2]))
        fprintf (stderr, "unable to search '%s'.\n", argv[1]);

    return 0;
}

输入文件示例

$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

使用/输出示例

$ /tmp/tmp-david/greplite dat/captnjack.txt Sea
[dat/captnjack.txt:4] On the Seven Seas.

注意代码中的注释——传递一个额外的参数来指示是否应该执行不区分大小写搜索(然后转换行和搜索-在搜索之前将术语小写)。

查看一下,如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 2016-02-09
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多