提问者:小点点

SIGABRT on std::ifstream关闭


1我目前正在做一个项目,创建我自己的游戏在OpenGL。 我现在的问题是,如果我读取一个文件,由于std::ifstream解构器(更具体地在“std::basic_ifstream>::~basic_ifstream()”中)中的某些内容,我读取该文件的函数会产生一个SIGABRT。 这个功能以前对我有用,但是突然停止工作了。

我的目标很简单:一个将文件读取到字符*的可靠实现。 多线程目前不是我关心的问题。

下面是我对文件读取功能的实现。 它接受一个路径,并应将该路径处的文件内容写入out参数中。

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>
#include <cassert>
#include "Utility.h"
char * Utility::readFile(const char* path,char*& out){
#ifndef NDEBUG
    std::cout<<"Getting file: "<<path<<"\n";
#endif
    // Open the file, but freak out if not valid.
    std::ifstream file=std::ifstream(path);
    assert(file.good());
    if(!file.good())
    {
        throw std::runtime_error((std::string)"Couldn't open file for loading: "+path);
    }

    // Read the file contents into a char buffer.
    std::stringstream buffer;buffer << file.rdbuf();
    std::string fileContentsStr = buffer.str();
    out = new char[fileContentsStr.size()];
    strcpy(out,fileContentsStr.c_str());
    return out;
}

我的代码位于C0D3-M4513R/OpenGGAME。 我已经尝试了一个最小的示例,它工作并使用相同的编译标志(链接器标志除外)。 test.txt和test1.txt只是包含一些在我的键盘上随机黑客生成的垃圾文本。

#include <cassert>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <cstring>

//This Function is the same as the one above!!!
char *readFile(const char *path, char *&out) {
#ifndef NDEBUG
    std::cout << "Getting file: " << path << "\n";
#endif
    // Open the file, but freak out if not valid.
    std::ifstream file = std::ifstream(path);
    assert(file.good());
    if (!file.good()) {
        throw std::runtime_error((std::string) "Couldn't open file for loading: " + path);
    }

    // Read the file contents into a char buffer.
    std::stringstream buffer;
    buffer << file.rdbuf();
    //convert the stringstream to a string
    std::string fileContentsStr = buffer.str();
    //copy the contents of the string to a char array
    out = new char[fileContentsStr.size()];
    strcpy(out, fileContentsStr.c_str());
    //return char array address (which should be the same as the start?)
    return out;
}

int main() {
    //The programm started!
    std::cout << "Hello, World!" << std::endl;
    //Define a space for the contents of the file to live
    char *out;
    //Read the contents of a file
    out = readFile("test.txt", out);
    //Print contents of the file
    std::cout << out << std::endl;
    char *out1;
    //Read the contents of a file
    out1 = readFile("test1.txt", out1);
    //Print contents of the file
    std::cout << out1 << std::endl;
    return 0;
}


共1个答案

匿名用户

strcpy:

将src指向的字符串(包括空终止符)复制到dest指向的第一个元素的字符数组。 如果目标数组不够大,则行为未定义。 如果字符串重叠,则行为未定义。

C_str:

返回指向空终止字符数组的指针,该数组的数据与存储在字符串中的数据等效。

out = new char[fileContentsStr.size()];
strcpy(out,fileContentsStr.c_str());

在将std::string与C字符串混合使用时需要小心,因为std::string不是空终止的,并且不计算nullterminator的大小。 但是,c_str确实返回一个指向空终止字符数组的指针。

您要求strcpyFileContentsStr.size()+1(大小+空终止符)写入只有FileContentsStr.size()元素的字符数组中。

PS:正如在一个注释中提到的,您应该考虑返回一个std::string。 您使用的是一个原始的拥有指针,这是容易出错的,应该避免。 要么使用智能指针,要么让std::string管理char-array(这就是它的实际用途)。