【问题标题】:Avoiding segmentation fault避免分段错误
【发布时间】:2013-11-25 18:31:00
【问题描述】:

我正在尝试将软件移植到 Linux。它在 Windows 上运行良好。 在 Linux 上,它在 strcmp 上给了我一个分段错误:

int main(void) {
    ...
    char* comando;
    char istruzione[100];
    scanf("%[^\n]%*c", istruzione);
    comando = strtok(istruzione, " ");
    if (strcmp(comando, "fput") == 0)
    ...
}

使用数组表示法可以解决问题,但我需要使用 * 表示法,因为我需要使用 strtok,它返回一个 * 字符。

【问题讨论】:

  • istruzione 是什么?
  • istruzione 已经分配了吗?它需要用于 scanf()
  • 我忘了复制那部分代码。这是一个简单的字符数组。
  • 在你的代码中使用 strcmp 后你是否也在使用 comando ?
  • 我找到了解决方案。我没有包含 string.h 标头。所以问题是:strcmp 有 2 个实现,一个在 stdlib 中,一个在 string.h 中?以及为什么确切的代码与 Windows 上的 string.h 标头配合得很好?

标签: c linux segmentation-fault scanf strcmp


【解决方案1】:

strtok 可以返回 NULL,这意味着你需要在 strcmp 中使用它之前检查它。

【讨论】:

  • 做一个简单的检查并没有解决问题。
  • 做一个简单的检查会阻止你在 strcmp 中使用 NULL 指针,并导致段错误。你的支票显示了什么?
  • 问题仍然存在,因为 strtok 在这种情况下没有返回 NULL。
  • 如果代码在 strcmp 上引发分段错误,即使您已明确测试它不为空,则 strcmp 很可能试图访问超出您为 istruzione 分配的 100 个字符的内存.如果程序读取的行长度超过 100 个字符,就会发生这种情况。按照我的建议使用fgets 而不是scanf 可以防止出现这种故障。
【解决方案2】:

作为 C 语言的一般规则,始终检查返回值,并始终检查函数返回的指针是否不为 NULL,然后再尝试对其进行任何操作。

在不知道程序输入的情况下,不知道是什么导致了这种分段错误,但我强烈建议您避免使用scanf,这可能会产生分段错误或更糟。在这里您可以安全地执行此操作:

if (fgets(istruzione, 100, stdin) != NULL) {
    comando = strtok(istruzione, " \n");
    if (comando != NULL) {
        if (strcmp(comando, "fput") == 0) {
            ....

您正在使用的scanf 调用读取一行文本而不复制换行符。 fgets 读取换行符,但您可以告诉 strtok 将其视为另一个分隔符以忽略它。

【讨论】:

  • @OP - 请检查这个答案是否是您所需要的。我建议您将所有scanf() 呼叫更改为fgets()
  • 已经尝试使用 fgets 没有成功。我发现唯一但不能接受的解决方案是使用数组而不是指针。
  • 我认为如果您需要更多帮助,您将需要提供一个完整的(小)程序以及导致它出现段错误的输入。 fgets 应该防止错误的输入,所以我看不出这段代码会产生任何错误。
【解决方案3】:

假设istruzione 是一个简单的字符缓冲区,我将以下测试放在一起。我观察到的一件事是,如果您只是按 ENTER 作为scanf 的输入,则执行strcmp 会导致分段错误。这是因为 strtok 返回 NULL,因为没有要标记的内容。

在使用comando 之前,您可能需要测试strtok 是否返回NULL 指针。您可以在下面的测试代码中看到我是如何做到这一点的。

scanf.c

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

char istruzione[256];

int main(void) {
    char* comando;
    scanf("%[^\n]%*c", istruzione);

    comando = strtok(istruzione, " ");

    /* test for NULL here */
    if (NULL != comando)
    {
        if (strcmp(comando, "fput") == 0)
            printf("%s\n", comando);
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-16
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多