问题
The following code gives a segmentation fault:
#include <iostream>
#include <fstream>
#include "binItr.h"
#include <boost/multi_array.hpp>
using namespace std;
int main(){
const char * xifile = "results/feretxiG1155V0P5T231K10.bin";
const uint pSize = 5;
const uint T = 231;
ifstream xiFileId(xifile, ios::binary);
typedef boost::multi_array<uint, 2> array_type;
array_type xi(boost::extents[T][pSize + 1]);
//the ii_t class in the following line is taken from http://stackoverflow.com/questions/1855704/c-binary-file-i-o-to-from-containers-other-than-char-using-stl-algorithms written by http://stackoverflow.com/users/14065/loki-astari
ii_t<uint> xi_in(xiFileId);
copy(xi_in, ii_t<uint>(), xi.data());
return 0;
}
The input binary file contains unsigned int
data and its size as reported by ls -l
is 231*(5+1)4 = 5544 bytes. I tried reading the file and storing the data in a vector and found that vector size is 231(5+1) = 1386. Analysis of the core file using gdb gives the following output.
Program terminated with signal 6, Aborted.
#0 0x00007fb71130ea75 in raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
in ../nptl/sysdeps/unix/sysv/linux/raise.c
(gdb) bt
#0 0x00007fb71130ea75 in raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007fb7113125c0 in abort () at abort.c:92
#2 0x00007fb7113484fb in __libc_message (do_abort=<value optimized out>, fmt=<value optimized out>) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#3 0x00007fb7113525b6 in malloc_printerr (action=3, str=0x7fb711425cd8 "double free or corruption (!prev)", ptr=<value optimized out>) at malloc.c:6266
#4 0x00007fb711358e83 in __libc_free (mem=<value optimized out>) at malloc.c:3738
#5 0x00000000004018c4 in __gnu_cxx::new_allocator<unsigned int>::deallocate (this=0x7fffc618d2f8, __p=0x2295290) at /usr/include/c++/4.4/ext/new_allocator.h:95
#6 0x000000000040152f in boost::multi_array<unsigned int, 2ul, std::allocator<unsigned int> >::deallocate_space (this=0x7fffc618d290) at /usr/include/boost/multi_array.hpp:484
#7 0x0000000000401077 in boost::multi_array<unsigned int, 2ul, std::allocator<unsigned int> >::~multi_array (this=0x7fffc618d290, __in_chrg=<value optimized out>) at /usr/include/boost/multi_array.hpp:468
#8 0x0000000000400d4e in main () at segTest.cpp:30
Any suggestions? Thanks.
回答1:
The problem is that the ii_t<>
input iterator class from the referred SO answer is 'reading' one too many items because the wrapped istream
doesn't return EOF
until the the dereference of the iterator after the one that returned the last item in the file. The extra returned data item is corrupting the allocated memory block in the multi_array
object.
If you change the ii_t<>
class to the following, you should get better behavior:
template<typename T>
struct ii_t: public iterator<input_iterator_tag, void, void, void, void>
{
ii_t(std::istream& str)
:m_str(&str)
{}
ii_t()
:m_str(NULL)
{}
ii_t& operator++() {return *this;} // increment does nothing.
ii_t& operator++(int){return *this;}
T& operator*()
{
// On the de-reference we actuall read the data into a local //// static ////
// Thus we can return a reference
static T result;
m_str->read(reinterpret_cast<char*>(&result),sizeof(T));
return result;
}
// If either iterator has a NULL pointer then it is the end() of stream iterator.
// Input iterators are only equal if they have read past the end of stream.
bool operator!=(ii_t const& rhs)
{
// we need to make sure we're not just about to hit EOF
// if we already haven't
if (m_str && m_str->good()) {
char dummy;
m_str->read(&dummy,1);
if (m_str->good()) {
m_str->putback(dummy);
}
}
if (rhs.m_str && rhs.m_str->good()) {
char dummy;
rhs.m_str->read(&dummy,1);
if (rhs.m_str->good()) {
rhs.m_str->putback(dummy);
}
}
bool lhsPastEnd = (m_str == NULL) || (!m_str->good());
bool rhsPastEnd = (rhs.m_str == NULL) || (!rhs.m_str->good());
return !(lhsPastEnd && rhsPastEnd);
}
private:
std::istream* m_str;
};
The relevant changes are in the bool operator!=(ii_t const& rhs)
function, where, if necessary, a dummy read is performed (then undone) on the wrapped istream
to determine if the istream is at the EOF.
Note that I'm making no claim that this is the best technique to handle the EOF
situation, but it seems to work.
来源:https://stackoverflow.com/questions/8004456/segmentation-fault-on-boostmulti-array