基于OpenCascade创建3次B-spline代码报错:内存溢出排查
OpenCascade 3次Clamped B样条创建问题排查与修复
问题概述
尝试使用OpenCascade创建一条3次Clamped B样条(包含5个控制点、9个节点),但代码运行时Visual Studio 2022提示内存溢出,原代码如下:
原头文件
#include <TColStd_Array1OfReal.hxx> #include <Geom_BSplineCurve.hxx> #include <gp_Pnt.hxx>
原创建函数
Handle(Geom_BSplineCurve) CreateBSplineCurve() //Create a handle pointer of B-spline with degree 3 { TColgp_Array1OfPnt controlPoints(1, 5); //set five control points controlPoints.SetValue(1, gp_Pnt(1, 1, 0)); controlPoints.SetValue(2, gp_Pnt(2, 3, 0)); controlPoints.SetValue(3, gp_Pnt(4, 5, 0)); controlPoints.SetValue(4, gp_Pnt(7, 3, 0)); controlPoints.SetValue(5, gp_Pnt(9, 6, 0)); TColStd_Array1OfReal knots(1, 9); // set 9 knots knots.SetValue(1, 0.0); knots.SetValue(2, 0.0); knots.SetValue(3, 0.0); knots.SetValue(4, 0.0); knots.SetValue(5, 0.5); knots.SetValue(6, 1.0); knots.SetValue(7, 1.0); knots.SetValue(8, 1.0); knots.SetValue(9, 1.0); TColStd_Array1OfInteger multiplicities(1,9); //every knots appear once multiplicities.SetValue(1, 1); multiplicities.SetValue(2, 1); multiplicities.SetValue(3, 1); multiplicities.SetValue(4, 1); multiplicities.SetValue(5, 1); multiplicities.SetValue(6, 1); multiplicities.SetValue(7, 1); multiplicities.SetValue(8, 1); multiplicities.SetValue(9, 1); Standard_Integer degree = 3; // set degree equal to 3 Handle(Geom_BSplineCurve) bsplineCurve = new Geom_BSplineCurve(controlPoints, knots, multiplicities, degree, Standard_False); return bsplineCurve; }
原主函数
int main() { Handle(Geom_BSplineCurve) bsplineCurve = CreateBSplineCurve(); std::cout << "Degree: " << bsplineCurve->Degree() << std::endl; return 0; }
错误分析
节点与重数的参数逻辑错误
OpenCascade的Geom_BSplineCurve构造函数要求:knots数组存放唯一的、非递减排列的节点值multiplicities数组对应每个节点的重复次数
原代码将重复节点全部放入knots数组,同时设置每个重数为1,完全违反参数规则,导致内部计算时出现非法内存访问。
Clamped B样条的重数设置错误
Clamped B样条要求首尾节点的重数等于样条次数+1(3次样条对应重数4),原代码未正确设置该重数,导致样条数学结构不合法,触发内存溢出。缺失必要头文件
使用TColgp_Array1OfPnt但未包含对应头文件<TColgp_Array1OfPnt.hxx>,可能引发编译或运行时异常。
修正后的代码
修正后的头文件
#include <TColStd_Array1OfReal.hxx> #include <Geom_BSplineCurve.hxx> #include <gp_Pnt.hxx> #include <TColgp_Array1OfPnt.hxx> // 补充缺失的头文件 #include <iostream> // 用于控制台输出
修正后的创建函数
Handle(Geom_BSplineCurve) CreateBSplineCurve() { // 定义5个控制点 TColgp_Array1OfPnt controlPoints(1, 5); controlPoints.SetValue(1, gp_Pnt(1, 1, 0)); controlPoints.SetValue(2, gp_Pnt(2, 3, 0)); controlPoints.SetValue(3, gp_Pnt(4, 5, 0)); controlPoints.SetValue(4, gp_Pnt(7, 3, 0)); controlPoints.SetValue(5, gp_Pnt(9, 6, 0)); // 唯一节点:按非递减顺序排列 TColStd_Array1OfReal knots(1, 3); knots.SetValue(1, 0.0); knots.SetValue(2, 0.5); knots.SetValue(3, 1.0); // 节点重数:首尾重数为4(3+1),中间节点重数1 TColStd_Array1OfInteger multiplicities(1, 3); multiplicities.SetValue(1, 4); multiplicities.SetValue(2, 1); multiplicities.SetValue(3, 4); Standard_Integer degree = 3; // 创建非周期Clamped B样条 Handle(Geom_BSplineCurve) bsplineCurve = new Geom_BSplineCurve( controlPoints, knots, multiplicities, degree, Standard_False ); return bsplineCurve; }
修正后的主函数
int main() { Handle(Geom_BSplineCurve) bsplineCurve = CreateBSplineCurve(); std::cout << "Degree: " << bsplineCurve->Degree() << std::endl; std::cout << "Is clamped spline: " << (bsplineCurve->IsClamped() ? "Yes" : "No") << std::endl; return 0; }
修正说明
- 节点数组改为唯一非递减值,重数数组对应每个节点的重复次数,符合OpenCascade构造函数的参数要求。
- 首尾节点重数设为4,满足Clamped B样条的定义:样条会通过首尾控制点,且首尾处的导数约束符合规范。
- 补充了缺失的头文件,消除潜在的编译问题。
内容的提问来源于stack exchange,提问作者ToastaFish
相关产品推荐
相关产品推荐

