【问题标题】:Getting a SEGFAULT on an unused symbol在未使用的符号上获取 SEGFAULT
【发布时间】:2020-12-11 02:01:38
【问题描述】:

我对 C 还是很陌生,所以如果我误解了一些基本的东西,请耐心等待

我有一个简单的程序,它应该将文件作为字符串读取,然后将该字符串拆分为行 - 将结果存储到 n 个字符串数组中。但是,当我运行以下代码时,我得到了一个 SEGFAULT - 使用 lldb 表明它是在 libsystem_platform.dylib 库中使用 strlen 时发生的,尽管我的代码中的任何地方都没有使用该函数。

这是完整的 FileIOTest.c 文件:

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

#define ENDL "\n"

void read_file(const char* path, char** destination) {
    FILE *file;
    long size_in_bytes;
    
    file = fopen(path, "r");
    
    if(file == NULL) {
        fputs("Requested file is invalid", stderr);
        exit(-1);
    }
    
    fseek(file, 0L, SEEK_END);
    size_in_bytes = ftell(file);
    
    fseek(file, 0L, SEEK_SET);  
    
    fread(*destination, sizeof(char), size_in_bytes, file);
    fclose(file);
}

int main() {
    char* file = calloc(1024, sizeof(char));
    read_file("run", &file);

    char* destination[2048];

    char* token = strtok(file, ENDL);
    for(int i = 0; token != NULL; i++) {
        destination[i] = token;
        token = strtok(NULL, ENDL);
    }

    for(int i = 0; i < 2048; i++)
        printf("%s", destination[i]);
}

我已经验证文件读取工作正常 - 所以我的字符串拆分代码肯定有问题,但我看不出究竟是什么问题

非常感谢任何帮助!

使用 clang 版本 clang-1103.0.32.62 编译的 lldb 版本 lldb-1103.0.22.10 的 macOS Catalina 15.4

【问题讨论】:

  • 答案不多,但calloc(1024, sizeof(char)) 是否有足够的内存来存储您的文件?
  • 为什么不查看整个调用堆栈而不仅仅是最后一个函数?
  • for(int i = 0; i &lt; 2048; i++) 如果令牌少于 2048 个怎么办?
  • @ChrisAkridge 文件读取成功并且可以打印,所以我认为那里没有问题:/
  • @user253751 我不完全确定如何使用 lldb 来解决这个问题 - 并且 gdb 在 Catalina 上已损坏

标签: c lldb llvm-clang


【解决方案1】:

您必须确保不超过目标大小。和 -1 表示空字符。

 fread(*destination, sizeof(char), min(size_in_bytes, destinationSize - 1), file);

destination[i] 不以空字符结尾。您不能将其用作 printf 的参数

for(int i = 0; i < 2048; i++)
    printf("%s", destination[i]); // can cause SEGFAULT

和另一个目的地限制检查。应添加 i

for(int i = 0; token != NULL && i < 2048; i++) {
    destination[i] = token;
    token = strtok(NULL, ENDL);
}

【讨论】:

  • 我已经解决了这个问题 - 文件读取代码没有问题,所以你的答案似乎不正确
  • 添加了另一个问题
  • 函数:fread() 不会为 NUL 终止缓冲区。
【解决方案2】:

事实证明,当您使用 %s 时 printf 在后台调用 strlen - 切换到 fputs 可以解决问题

【讨论】:

  • 与其通过 fputs'ing NULL 指针来解决问题,不如在打印之前检查 NULL (if (destination[i] != NULL) { printf("%s", destination[i]); }。您还应该确保不要拆分超过 2048 个令牌,因为这是一个完整的额外问题列表。
猜你喜欢
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多