将数组传递给C ++函数时的Segfault

时间:2017-03-09 10:15:45

标签: c++

我正在编写一个函数来从C ++中的二进制文件中读取数组。这是我的功能:

#include <iostream>
#include <fstream>

template <typename T>
int bread(T array_out[], int array_size, const char FILENAME[]) {
    // Open file
    std::ifstream input_file (FILENAME, std::ios::in | std::ios::binary
            | std::ios::ate);
    // Check that the file was opened correctly
    if (input_file.is_open()) {
        // Check that the file size matches the array size
        std::streampos file_size = input_file.tellg();
        if (file_size == array_size) {
            // Read the array contents from the file
            input_file.seekg(0, std::ios::beg);
            input_file.read(reinterpret_cast<char *>(&array_out), array_size);
            // Close file
            input_file.close();
        } else {
            std::cerr << "File " << FILENAME << " is not of expected size.\n";
            std::cerr << "  File size:\t" << file_size << " B\n";
            std::cerr << "  Expected\t" << array_size << " B\n";
            // Close file
            input_file.close();
            return -2;
        }
    } else {
        std::cerr << "Failed to open file " << FILENAME << "\n";
        return -1;
    }

    return 0;
}

如果没有| std::ios::ate,则会计算文件大小为0并返回-2。这是有道理的。

但是只要我包含| std::ios::ate(或者,作为替代,input_file.seekg(0, std::ios::end);),函数的执行就会失败并出现段错误。在某些情况下,明确地在文件中查找是有效的,因为input_file.seekg(0, std::ios::beg);按预期工作。

我的猜测是输入文件中可能没有EOF标记。如果是这种情况,有没有办法安全地处理它?<​​/ p>

编辑:此处调用此函数:

int verify_buff[SIZE];
Ierr = bread(verify_buff, sizeof(verify_buff), "serial.bin");
if (Ierr != 0) {
    std::cerr << "Error " << Ierr << " in function bread\n";
    return Ierr;
}

其中SIZE是一个定义为1024的全局常量。

在segfault,

array_size = 4096
array_out = 0x7ffd5dca20e0

完整段错误消息:

[physlogin:81411] *** Process received signal ***
[physlogin:81411] Signal: Segmentation fault (11)
[physlogin:81411] Signal code: Address not mapped (1)
[physlogin:81411] Failing at address: 0x1
[physlogin:81411] [ 0] /lib64/libpthread.so.0[0x3cb300f7e0]
[physlogin:81411] [ 1] /lib64/libc.so.6(fclose+0x4)[0x3cb2466344]
[physlogin:81411] [ 2] /usr/lib64/libstdc++.so.6(_ZNSt12__basic_fileIcE5closeEv+0x4c)[0x3cb78ba5ac]
[physlogin:81411] [ 3] /usr/lib64/libstdc++.so.6(_ZNSt13basic_filebufIcSt11char_traitsIcEE5closeEv+0xb7)[0x3cb786cb77]
[physlogin:81411] [ 4] /usr/lib64/libstdc++.so.6(_ZNSt14basic_ifstreamIcSt11char_traitsIcEE5closeEv+0xd)[0x3cb786ebfd]
[physlogin:81411] [ 5] Q3_gw639.exe[0x40dec5]
[physlogin:81411] [ 6] Q3_gw639.exe[0x40ea06]
[physlogin:81411] *** End of error message ***

1 个答案:

答案 0 :(得分:2)

一个主要问题是您在此致电read

 input_file.read(reinterpret_cast<char *>(&array_out), array_size);

由于array_out已经是T*,因此该行尝试读入指针的地址。这是不正确的 - 你想要做的是:

 input_file.read(reinterpret_cast<char *>(array_out), array_size);

请注意您的功能声明:

template <typename T>
int bread(T array_out[], int array_size, const char FILENAME[]) 

与此不同:

template <typename T>
int bread(T* array_out, int array_size, const char* FILENAME) 

即使第一个看起来它正在接收一个数组,它也不是。按名称传递数组会衰减传递给指针的参数,因此您正在处理函数中的指针。