What are the differences of valarray in gcc and msvc (or Linux and Windows)

667 views Asked by At

I experience different behavior of valarray in Windows and Linux. Does anyone know about this or know where to look at? It is obvious, the one version working on both system is correct C++, but why does the other works in Windows? Are there more differences in the implementation of valarray?

Example of Code working on MSVC/Windows but not on gcc/Linux:

    valarray<signed short> myValues;
    for(size_t s = 0; s < 10; s++)
    {
        slice dataSlice(1, 1, 1);
        // on Linux, this slice operation gives me a segmentation fault
        myValues= RawData[dataSlice];
    }

I tracked it down to fix the code like this for the gcc/Linux version:

    for(size_t s = 0; s < 10; s++)
    {
        slice dataSlice(1, 1, 1);
        valarray<signed short> myValues = RawData[dataSlice];
    }

The gcc/Linux versions expectes the l-value (myValues) is initialized already. This does not seem to be necessary on MSVC/Windows. I could call myValues.resize(1) on Linux and it works as well.

Now, does anyone knows about the differences exactly or a resource on the internet? Are there best practices how to work with the valarray?

Software versions:

  • Windows 7, MS Visual Studio 2010 SP1, Visual C++ Compiler 16.00.40219.01 for 80x86
  • Lubuntu 14.04 64 Bit on Virtual Machine, GNU Make 3.81, GCC 4.8.2

Thanks everyone.


Update: Detailed code example. Does compile. The first example gives segmentation fault in Linux, but works well in Windows.

// This example compiles both on Windows with MSVC and on Linux with GCC.
// It gives a segmentation fault in Linux.
// It gives the expected output on Windows.

#include "stdafx.h"

#include <iostream>
#include <valarray>

int main(int argc, char **argv) {

  //init base data

  std::valarray<signed short> myData(10);
  for (int i = 0; i < 10; i++)
  {
    myData[i] = i;
  }

  std::valarray<signed short> myValues;

  for (int i = 0; i < 10; i++)
  {
    myValues = myData[std::slice(0, i, 1)];
    std::cout << "myValues: ";

    for (size_t k = 0; k < myValues.size(); k++)
    {  
        std::cout << myValues[k] << ",";
    }

    std::cout << std::endl;
  }
}

The following example works well on Linux and Windows. Note the declaration and therfore initialization of myValues inside the for loop, right where the slicing is done.

#include "stdafx.h"

#include <iostream>
#include <valarray>

int main(int argc, char **argv) {

  //init base data

  std::valarray<signed short> myData(10);
  for (int i = 0; i < 10; i++)
  {
    myData[i] = i;
  }

  for (int i = 0; i < 10; i++)
  {
    std::valarray<signed short> myValues = myData[std::slice(0, i, 1)];
    std::cout << "myValues: ";

    for (size_t k = 0; k < myValues.size(); k++)
    {  
        std::cout << myValues[k] << ",";
    }

    std::cout << std::endl;
  }
}

Expected output:

myValues:
myValues: 0,
myValues: 0,1,
myValues: 0,1,2,
myValues: 0,1,2,3,
myValues: 0,1,2,3,4,
myValues: 0,1,2,3,4,5,
myValues: 0,1,2,3,4,5,6,
myValues: 0,1,2,3,4,5,6,7,
myValues: 0,1,2,3,4,5,6,7,8,
1

There are 1 answers

6
Paul On

valarray.assign/8:

valarray<T>& operator=(const slice_array<T>&);
valarray<T>& operator=(const gslice_array<T>&);
valarray<T>& operator=(const mask_array<T>&);
valarray<T>& operator=(const indirect_array<T>&);

Requires: The length of the array to which the argument refers equals size().

You create myValues as an empty valarray with size 0. Precondition for using valarray<T>& operator=(const slice_array<T>&); is not met.

Replace

myValues = myData[std::slice(0, i, 1)];

with

auto s = std::slice(0, i, 1);
myValues.resize(s.size());
myValues = myData[s];

or

myValues = std::valarray<signed short>(myData[std::slice(0, i, 1)]);

and it will work.

What I don't understand yet is why slice_array<T> operator[](slice slicearr) is chosen instead of valarray<T> operator[](slice slicearr) const.