Skip to content

Runtime crash in xtensor #2861

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions