Re: STL::glice vs cstdio
On 20 Jun., 21:57, n...@cam.ac.uk wrote:
I have some code where executing some completely irrelevant calls in
cstdio causes gslice to throw a segmentation fault; a previous code
(which was buggy) caused the use of gslice to cause cerr/cout to
throw away all their output! Now, the most likely explanation is
that I have missed some critical constraint on the use of gslice
arrays, but blowed if I can spot one.
This was under Linux, and I shall retry under Microsoft tomorrow
(if our local systems have enough compiler support). The original
program was solid with checking, so it's not a simple bounds error.
The appended code is really stripped down and fails if the argument
count is greater than 1 but not otherwise.
Any suggestions welcome.
I checked your code analytically and I found only
little, nevertheless, I hope it might help you.
Let me first ask a question: According to which
standard (C++98, C++03, C++0x) did you compile your
code? (See below, why)?
life.cpp:
using namespace std;
I'm not kidding, but did you really write this using-
directive *in front* of the std headers and w/o any
previous namespace std definition? If so, your
compiler must be very tolerant (it should not even
be allowed in C++98 to use a using-directive w/o
a previous namespace definition) and I strongly suggest
to move this directive after the include's.
#include <valarray>
#include <cstdio>
class Matrix {
private:
valarray<signed char> *base;
int stride, offset;
public:
Matrix (int lwb1, int lim1, int lwb2, int lim2);
gslice_array<signed char> slice (int lwb1, int lim1, int lwb2, int lim2);
};
Matrix::Matrix (int lwb1, int lim1, int lwb2, int lim2) {
this->base = new valarray<signed char>((size_t)((lim1-lwb1)*(lim2-lwb2)));
this->stride = lim2-lwb2;
this->offset = lwb1*this->stride+lwb2;
}
gslice_array<signed char> Matrix::slice (int lwb1, int lim1,
int lwb2, int lim2) {
static valarray<size_t> length(2), stride(2);
length[0] = lim1-lwb1;
length[1] = lim2-lwb2;
stride[0] = this->stride;
stride[1] = 1;
return (*this->base)[gslice(lwb1*this->stride+lwb2-offset,length,stride)];
}
As of C++98/03 this code should be ill-formed, because
std::gslice_array is not copyable. You should look
carefully at this, because if the compiler accepts
this, it might just work or - with some bad luck - it
might produce something nasty. This restriction has
been removed as of C++0x, though.
Let me note that I also looked for some particular
problem which might hit you - at least theoretically:
The standard says in all three versions that you meet
undefined behaviour, if the non-const overload of
valarray's operator[](const gslice&) sees degenerate
indices. I did calculate your indices by hand, but
I didn't find a violation of this restriction.
I also checked for normal boundary violations but I
didn't find any. This doesn't mean that there aren't any,
but I want just to give you the best information at
your hands that are available to me.
Last but not least I tried your code with the Visual
Studio 2008 compiler with a lot of runtime diagnostic
activated, but did not hit your problem (But I needed to
move your using directive after the std header includes
to get it accepted by the compiler).
Sorry, this is all I found. My best guess is that this
is indeed a defect in your valarray implementation.
Good luck & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]