pybind / pybind11

Seamless operability between C++11 and Python
https://pybind11.readthedocs.io/
Other
15.33k stars 2.07k forks source link

[BUG]: Segmentation fault Mac Clang #4551

Closed petrasvestartas closed 1 year ago

petrasvestartas commented 1 year ago

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

The most recent

Problem description

I pybinded C++ methods, all of them works except on of them, that produces a "Segmentation fault". What could be a cause of this error and how to debug it?

Reproducible example code

def get_connection_zones(
    input_polyline_pairs,
    input_insertion_vectors=None,
    input_joints_types=None,
    input_three_valence_element_indices_and_instruction=None,
    input_adjacency=None,
    joint_parameters_and_types=None,
    search_type=0,
    scale=[1, 1, 1],
    output_type=4,
    flatten_output=False,
):
    """detect connection zones between two polylines and generate joinery
    Parameters
    ----------
    input_polyline_pairs : list[Polyline]
        list of polylines of top and bottom outlines
    input_insertion_vectors : list[list[Vector],list[Vector],list[Vector]], optional
        list of lists of insertion vectors for each polyline side: top, bottom and sides
    input_joints_types : list[list[int],list[int],list[int]], optional
        list of lists of joint types for each polyline side: top, bottom and sides
    input_three_valence_element_indices_and_instruction : list[list[int],list[int],list[int]], optional
        list of lists of 4 valence elements e.g. [[0],[0,4,1,4],[5,4,6,4]], the first item points to special corner cases: 0 - Annen Case 1 - Vidy Case
    input_adjacency : list[int], optional
        list of adjacency between polylines elements and faces, often sides are ignored e.g. [0,1,-1,-1,5,8,-1,-1]
    joint_parameters_and_types : list[double], optional
        a list of triplets:
        300, 0.5, 3,   // 1-9 ss_e_ip (side-to-side edge in-plane)
        450, 0.64, 15, // 10-19 ss_e_op (side-to-side edge out-of-plane)
        450, 0.5, 20,  // 20-29 ts_e_p (top-to-side edge plane)
        300, 0.5, 30,  // 30-39 cr_c_ip (cross cutting in-plane)
        6, 0.95, 40,   // 40-49 tt_e_p  (top-to-top edge plane)
        300, 0.5, 58,  // 50-59 ss_e_r (side-to-side edge rotated)
        300, 1.0, 60   // 60-69 b (boundary)
    search_type : int, optional
        0 - side-to-side, 1 - cross, 2 - all
    scale : list[double], optional
        a list of 3 doubles for scaling the joint
        for beams you might need bigger cuts
        for plates you might need smaller cuts
    output_type : int, optional
        what_to_expose:
        0 - Plate outlines
        1 - wood::joint lines
        2 - wood::joint areas
        3 - wood::joint areas with bounding box
        4 - wood::joint areas with bounding box and cut types
    Returns
    -------
    list[Polyline]
        A list of top and bottom polylines
    """

    ###################################################################################################
    # convert compas polylines to nested vector of doubles
    ###################################################################################################

    _input_polyline_pairs_coord = WoodNestedVectorDouble([])
    _input_insertion_vectors_coord = WoodNestedVectorDouble([])
    _input_joints_types = WoodNestedVectorInt([])
    _input_three_valence_element_indices_and_instruction = WoodNestedVectorInt([])
    _input_adjacency = WoodVectorInt([])

    _input_polyline_pairs_coord = polylines_to_WoodNestedVectorDouble(
        input_polyline_pairs
    )  # input_polyline_pairs

    if input_insertion_vectors is not None:
        _input_insertion_vectors_coord = lists_of_vectors_to_WoodNestedVectorDouble(
            input_insertion_vectors
        )  # input_insertion_vectors

    if input_joints_types is not None:
        _input_joints_types = lists_to_WoodNestedVectorInt(
            input_joints_types
        )  # input_joints_types

    if input_three_valence_element_indices_and_instruction is not None:
        _input_three_valence_element_indices_and_instruction = (
            lists_to_WoodNestedVectorInt(
                input_three_valence_element_indices_and_instruction
            )
        )
        # (input_three_valence_element_indices_and_instruction)

    if input_adjacency is not None:
        _input_adjacency = list_to_WoodVectorInt(input_adjacency)  # input_adjacency

    _joint_parameters_and_types = WoodVectorDouble(
        [
            300.0,  # 1-9 ss_e_ip (side-to-side edge in-plane)
            0.5,
            3.0,
            200.0,  # 10-19 ss_e_op (side-to-side edge out-of-plane)
            0.66,
            10.0,
            300.0,  # 20-29 ts_e_p (top-to-side edge plane)
            0.5,
            20.0,
            300.0,  # 30-39 cr_c_ip (cross cutting in-plane)
            0.5,
            30.0,
            6.0,  # 40-49 tt_e_p  (top-to-top edge plane)
            0.95,
            40.0,
            300.0,  # 50-59 ss_e_r (side-to-side edge rotated)
            0.5,
            58.0,
            300.0,  # 60-69 b (boundary)
            1.0,
            60.0,
        ]
    )

    if (
        joint_parameters_and_types is not None
    ):  # if the user has provided joint parameters
        for i in range(len(joint_parameters_and_types)):
            _joint_parameters_and_types[i] = joint_parameters_and_types[i]

    _output_plines = WoodNestedNestedVectorDouble([])
    _output_types = WoodNestedVectorInt([])
    _scale = WoodVectorDouble([1.0, 1.0, 1.0])

    if scale is not None:  # if the user has provided joint parameters
        for i in range(len(scale)):
            _scale[i] = scale[i]

    ###################################################################################################
    # run the WOOD CPP code
    ###################################################################################################

    print(
        "\n___________________________________start_of_WOOD_____________________________________"
    )

    # print(_input_polyline_pairs_coord)
    # print(_input_insertion_vectors_coord)
    # print(_input_joints_types)
    # print(_input_three_valence_element_indices_and_instruction)
    # print(_input_adjacency)
    # print(_joint_parameters_and_types)
    # print(search_type)
    # print(_scale)
    # print(output_type)
    # print(_output_plines)
    # print(_output_types)

    start_time = time.time()
    wood_pybind11.get_connection_zones(
        # input
        _input_polyline_pairs_coord,
        _input_insertion_vectors_coord,
        _input_joints_types,
        _input_three_valence_element_indices_and_instruction,
        _input_adjacency,
        _joint_parameters_and_types,
        search_type,
        _scale,
        output_type,
        # output
        _output_plines,
        _output_types,
    )

    print(
        "\n______________________________________ %s ms ______________________________________"
        % round((time.time() - start_time) * 1000.0, 2)
    )
    print(
        "\n____________________________________end_of_WOOD______________________________________"
    )

    ###################################################################################################
    # convert nested vector of doubles to a list of polylines
    ###################################################################################################

    ###################################################################################################
    # output
    ###################################################################################################
    if flatten_output:
        return WoodNestedNestedVectorDouble_to_polylineslist(_output_plines)
    else:
        return WoodNestedNestedVectorDouble_to_polylineslists(_output_plines)

def closed_mesh_from_polylines(list_of_polylines):
    """Convert a list of polylines to a closed mesh.

    Parameters
    ----------
    list_of_polylines : list[Polyline]
        list of polylines with holes, for meshing plates

    Returns
    -------
    Mesh
        A closed mesh for top and bottom polylines
    """

    ###################################################################################################
    # conversion of input data
    ###################################################################################################
    list_of_polylines_coordinates = polylines_to_WoodNestedVectorDouble(
        list_of_polylines
    )

    ###################################################################################################
    # run the WOOD CPP code
    ###################################################################################################

    print(
        "\n___________________________________start_of_WOOD_____________________________________"
    )

    start_time = time.time()
    out_vertices = WoodVectorFloat()
    out_normals = WoodVectorFloat()
    out_triangles = WoodVectorInt()

    wood_pybind11.closed_mesh_from_polylines_vnf(
        # input
        list_of_polylines_coordinates,
        # output
        out_vertices,
        out_normals,
        out_triangles,
    )

    print(
        "\n______________________________________ %s ms ______________________________________"
        % round((time.time() - start_time) * 1000.0, 2)
    )
    print(
        "\n____________________________________end_of_WOOD______________________________________"
    )

    ###################################################################################################
    # conversion of output data
    ###################################################################################################
    return WoodVectorFloat_and_WoodVectorInt_to_mesh(out_vertices, out_triangles)

Is this a regression? Put the last known working version here if it is.

Not a regression

petrasvestartas commented 1 year ago

It would be great if someone could tell how to debug segmention fault errors.

petrasvestartas commented 1 year ago

Found the error, I used printf() until I found the issue. The vector was empty while I was trying to get the last element of it. MSVC ingores such error, Clang does not. Pfew...