【问题标题】:Debugging my string tokenizer with gdb使用 gdb 调试我的字符串标记器
【发布时间】:2016-01-18 00:19:28
【问题描述】:

我有一小段代码,它将换行符分隔的单词作为输入,并将 (word,1) 作为输出。代码如下:

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

int main(int argc, char *argv[]) {
    char *str1, *str2, *token;
    char *saveptr1;
    char buffer[100];
    while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
        token = strtok_r(buffer, '\n', &saveptr1);
        printf("(%s,1)\n", token);
    } 
    exit(EXIT_SUCCESS);
}

此代码可以正常工作并提供预期的输出。但是,当我使用 gdb 单步执行代码时,在第 9 行出现以下错误:strtok_r 行。

程序收到信号SIGSEGV,分段错误。 strtok_r () 在 ../sysdeps/x86_64/strtok.S:101 101 ../sysdeps/x86_64/strtok.S: 没有这样的文件或目录。

这令人费解。我什至没有“踏入”strtok_r 行,我只是在“下一个”它,即跨过。为什么在 GDB 期间会抛出此错误?我很焦虑,因为我有一个真正的、更大的程序,因为这个问题我无法调试。事实上,对于大多数字符串函数(strncmpstrncpy)都会出现这个问题。

编辑:编译器确实警告过在这一行没有强制转换的整数赋值指针,我应该把 2 和 2 放在一起。

【问题讨论】:

  • 这似乎已经做到了..这非常令人惊讶...我虽然 \n 转义序列仍然只算作一个字符...
  • 开启 -Wall 警告。它会拯救你。
  • '\n' 是一个字符,但 strtok_r 需要一个指针,因此您传递 const char 指针“\n”
  • 谢谢特伦斯。这就说得通了;但是,程序为什么会编译运行呢? C 的另一种未定义行为? :(
  • 它不应该在没有警告的情况下在 C99 或 C11 下编译,因为strtok_r() 在使用之前没有声明(因此编译器不知道参数的类型),或者因为对strtok_r() 的调用是错误的。你用什么命令行来编译这个,在哪个平台上?您应该确保您的编译器在启用大部分警告的情况下运行(例如,对于 GCC,您可以使用gcc -Werror -Wall -Wextra;我添加了-Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition,因为它们对我来说是一个严重的问题,我有时也会添加其他选项) .

标签: c string segmentation-fault gdb


【解决方案1】:

您将字符文字而不是字符串文字传递给 strtok_r,库函数 strtok_r 在尝试取消引用无效指针时崩溃。

GDB 尝试显示位于../sysdeps/x86_64/strtok.S 中的strtok_r 的汇编源代码(它从标准C 库调试信息中知道这一点),但在该位置找不到源文件。

您当然应该这样更正代码:

token = strtok_r(buffer, "\n", &saveptr1);

最好使用-Wall -Wextra -Werror 启用来自编译器的尽可能多的警告并修复代码,直到编译器不再检测到任何可疑代码。

事实上,你提到使用strncpy:这个函数非常容易出错。它不像大多数人认为的那样做,它永远不是正确的工具。阅读它的文档并仔细验证您是否正确使用它,以及在这些地方是否没有更好的选择。

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    相关资源
    最近更新 更多