Skip to content

Runtime crash in xtensor #2861

@Sallee1

Description

@Sallee1

Environment:

  • xtensor: 0.25.0

  • xtl: 0.7.7

  • xsimd: 13.2.0

  • OS: Windows 11 24H2

  • Compiler: MSVC 19.44 (Visual Studio 2022)

  • C++ Standard: C++14

  • Compilation flags:

    /permissive- /ifcOutput "x64\Release\" /GS /GL /W3 /Gy /Zc:wchar_t 
    /I"xtensor-0.25.0\include" /I"xtl-0.7.7\include" /I"xsimd-13.2.0\include" 
    /Zi /Gm- /Od /Ob0 /sdl /Fd"vc143.pdb" /Zc:inline /fp:precise 
    /D "XTENSOR_USE_XSIMD" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" 
    /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /std:c++17 /FC 
    /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"demo.pch" 
    /diagnostics:column /utf-8
    
  • Linking flags:

    /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"demo.pdb" /DYNAMICBASE 
    "opencv_core4100.lib" ...(other libs)... /DEBUG /MACHINE:X64 /OPT:REF 
    /SUBSYSTEM:CONSOLE /LTCGOUT:"demo.iobj" /OPT:ICF /ERRORREPORT:PROMPT 
    /LIBPATH:"opencv_lib_path"
    

Description:
It might be the following statement that caused the subsequent lazy evaluation to crash:

auto mfd_flow_weight = mfd_flow_weight_unnorm / mfd_flow_weight_sum;  // [H,W,8]

And the following statement triggers lazy evaluation, resulting in a segmentation fault:

xt::xtensor<double, 3>  result = mfd_flow_weight;

Minimal Reproducible Example:

#include <xtensor.hpp>
#include <opencv2/opencv.hpp>
using namespace xt::placeholders;
/**
 * @brief Sliding window view similar to numpy
 * @param img Input image
 * @param shape Window size
 * @return Sliding window view
*/
xt::xtensor<double, 4> sliding_window_view(const xt::xtensor<double, 2>& img, const std::array<size_t, 2>& shape, const std::array<size_t, 2>& stride = { 1,1 }) {
    assert((shape[0] & 1) == 1 && (shape[1] & 1) == 1);
    assert(stride[0] > 0 && stride[1] > 0);
    xt::svector<size_t, 4> new_shape{
        (img.shape(0) - shape[0]) / stride[0] + 1,
        (img.shape(1) - shape[1]) / stride[1] + 1,
        shape[0],
        shape[1] };
    xt::svector<std::ptrdiff_t, 4> new_strides{
        static_cast<std::ptrdiff_t>(stride[0] * img.strides()[0]),
        static_cast<std::ptrdiff_t>(stride[1] * img.strides()[1]),
        img.strides()[0],
        img.strides()[1]
    };
    auto sliding_window = xt::strided_view(img, new_shape, std::move(new_strides), 0);
    return sliding_window;
}
xt::xtensor<double, 3> mfd(xt::xtensor<double,2> dem, double dem_resolution) {
    // Sliding window view
    auto dem_pad = xt::pad(dem, 1, xt::pad_mode::constant, 0);            // [H+2,W+2]
    auto dem_slide_window = sliding_window_view(dem_pad, { 3,3 });         // [H,W,3,3]
    // Elevation differences
    auto diffs = xt::maximum(0,
        xt::view(dem_slide_window, xt::all(), xt::all(), xt::range(1, 2), xt::range(1, 2)) - dem_slide_window);   // [H,W,3,3]
    // Remove center
    auto diffs_without_center = xt::view(
        xt::reshape_view(diffs, { diffs.shape(0), diffs.shape(1), 9ULL }),
        xt::all(), xt::all(), xt::drop(4));            // [H,W,8]
    // Compute gradients
    const double diag_dist = dem_resolution * sqrt(2);
    xt::xtensor_fixed<double, xt::xshape<8>> slope_dist{
        diag_dist, dem_resolution, diag_dist,
        dem_resolution, dem_resolution,
        diag_dist, dem_resolution, diag_dist };        // [8]
    auto gradient8 = diffs_without_center / slope_dist;     // [H,W,8]
    auto max_gradient = xt::amax(gradient8, 2, xt::keep_dims);     // [H,W,1]
    std::cout << xt::adapt(max_gradient.shape()) << std::endl;
    // Compute flow concentration coefficient
    auto mfd_p = 8.9 * xt::minimum(max_gradient, 1.0) + 1.1;   // [H,W,1]
    std::cout << xt::adapt(mfd_p.shape()) << std::endl;
    // Compute unnormalized flow weights
    xt::xtensor_fixed<double, xt::xshape<8>> mfd_l{
        0.354,0.5,0.354,
        0.5,      0.5,
        0.354,0.5,0.354,
    };        // [8]
    auto mfd_flow_weight_unnorm = xt::pow(gradient8, mfd_p) * mfd_l;        // [H,W,8]
    auto mfd_flow_weight_sum = xt::sum(mfd_flow_weight_unnorm, 2, xt::keep_dims);        // [H,W,1]
    // Normalize the flow weights
    auto mfd_flow_weight = mfd_flow_weight_unnorm / mfd_flow_weight_sum;    // [H,W,8]
    xt::xtensor<double, 3>  result = mfd_flow_weight;
    std::cout << result << std::endl;
    return result;
}
int main() {
    cv::Mat dem_img = cv::imread("assets/dem.tif", cv::IMREAD_UNCHANGED);
    dem_img.convertTo(dem_img, CV_64FC1);
    xt::xtensor<double, 2> dem_tensor = xt::adapt(dem_img.data, dem_img.total(), xt::no_ownership(), 
        std::array<size_t, 2>{ static_cast<size_t>(dem_img.rows), static_cast<size_t>(dem_img.cols) });
    double resolution = 30.0;
    auto result = mfd(dem_tensor, resolution);
}

Attachments:

The call stack, executable program, pdb debug information, and minidump are provided in the following onedrive sharing

https://1drv.ms/u/c/4d2e14be0cb87b34/EWKRw2KHtwRDj8MKgIbLOy0Bc_LxLcAdvdhQXscQoLNX4g?e=gzj9ES

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions