沉默流星 发表于 2025-2-17 17:28:26

为什么调试版报错

问题如下:
当使用调试版生成的dll则报错,编译版本则没有问题。


static/image/hrline/1.gif
调用的火山类中的函数代码,火山生成的C++拿到VS当中调试则没有任何问题


static/image/hrline/1.gif
代码如下:
<火山程序 类型 = "通常" 版本 = 1 />

类 区域调用类 <公开>
{
    方法 创建区域 <公开 静态 @输出名 = "qy" @视窗.输出 = 真>
    {
      变量 ss <类型 = ads_name>
      变量 rt <类型 = 整数>
      rt = 取选择集 ("0", 0, 0, 0, ss)
      // 根据选择集中的对象构建边界曲线的ID数组
      变量 对象ID数组 <类型 = AcDb对象ID数组>
      如果 (rt == ADS错误代码.请求成功)
      {
            变量 长度 <类型 = 整数>
            取选择集长度 (ss, 取变量地址 (长度))// 17行有错误
            变量 计次 <类型 = 整数 值 = 0>
            循环 (0, 长度, 计次, 1)
            {
                变量 ent <类型 = ads_name>
                取选择集实体名称 (ss, 计次, ent)
                变量 对象ID <类型 = AcDb对象ID>
                取对象ID (对象ID, ent)
                对象ID数组.添加 (对象ID)

            }

      }
      释放选择集资源 (ss)
      变量 区域ID列表 <类型 = AcDb对象ID数组>
      区域ID列表 = 区域工具类.添加面域 (对象ID数组)// 这句代码,如果是调试版本则报错,如果是编译版本则没问题
      // 区域工具类.添加面域 (对象ID数组)
      变量 编号 <类型 = 整数>
      编号 = 区域ID列表.取成员数 ()
      AcDb格式化输出 ("已经创建%d个面域", 编号)

    }

    #
}
对应调用的函数代码如下:
<火山程序 类型 = "通常" 版本 = 1 />

类 区域工具类 <公开 注释 = "CRegionUtil">
{

    # //创建面域

    方法 添加面域 <公开 静态 类型 = AcDb对象ID数组 @输出名 = "kkl">
    参数 曲线ID <类型 = AcDb对象ID数组>
    {
      变量 对象ID数组 <类型 = AcDb对象ID数组 注释 = "生成的面域的ID数组">
      变量 空指针数组 <类型 = AcDb空指针数组 注释 = "指向作为面域边界的曲线的指针的数组">
      变量 空指针数组2 <类型 = AcDb空指针数组 注释 = "指向创建的面域对象的指针的数组">
      变量 实体指针 <类型 = AcDb实体指针 注释 = "临时指针,用来关闭边界曲线">
      变量 区域指针 <类型 = AcDb区域指针 注释 = "临时对象,用来将面域添加到模型空间">
      // 用曲线ID初始化空指针数组
      变量 计次 <类型 = 整数 值 = 0>
      循环 (计次, 曲线ID.取成员数 (), 计次, 1)
      {
            打开数据库实体 (实体指针, 曲线ID.取数组索引 (计次), 打开模式类.kForRead, )
            如果 (实体指针.是否属于 (AcDb曲线类.描述 ()))// 可能出现问题
            {
                空指针数组.添加 (实体指针)// 可能出现问题

            }

      }
      变量 错误 <类型 = 整数>
      错误 = AcDb区域.根据曲线段创建区域 (空指针数组, 空指针数组2)
      如果 (错误 == 0)
      {
            // 将生成的面域添加到模型空间
            变量 计次2 <类型 = 整数 值 = 0 @输出名 = "jc2">
            循环 (计次2, 空指针数组2.取成员数 (), 计次2, 1)
            {
                区域指针 = 空指针数组2.取元素 (计次2)// 可能出现问题
                区域指针.置数据库默认设置 ()
                变量 区域ID <类型 = AcDb对象ID>
                变量 数据库指针 <类型 = AcDb数据库指针>
                区域ID = 实体空间类.添加实体到模型空间 (区域指针, 数据库指针)
                对象ID数组.添加 (区域ID)

            }
      }
      否则
      {
            // 如果创建不成功,也要删除已经生成的面域
            变量 计次3 <类型 = 整数>
            循环 (计次3, 空指针数组2.取成员数 (), 计次3, 1)
            {
                // 释放内存

            }

      }
      // 关闭作为边界的对象
      变量 计次4 <类型 = 整数>
      循环 (计次4, 空指针数组.取成员数 (), 计次4, 1)
      {
            实体指针 = 空指针数组.取元素 (计次4)
            AcDb对象实体类.关闭 (实体指针)

      }
      返回 (对象ID数组)
    }

    #
}


沉默流星 发表于 2025-2-17 17:35:21


是不是这个对象数组类封装的不对
封装代码如下:父类<火山程序 类型 = "通常" 版本 = 1 />

类 Ac数组类 <公开 注释 = "AcArray<模板类型1>" "//@别名" = @"//\"AcArray<模板类型1>\"" @模板基础类 = 真 @别名类型 = 本地类 "">
{
    方法 取成员数 <公开 静态 类型 = 整数 @嵌入式方法 = "">
    参数 欲操作本对象 <类型 = Ac数组类 "//@匹配类型" = 所有类型>
    {
      @ @<欲操作本对象>.length()
    }

    方法 取数组索引 <公开 静态 类型 = 模板类型1 @嵌入式方法 = "">
    参数 欲操作本对象 <类型 = Ac数组类>
    参数 索引值 <类型 = 整数>
    {
      @ @<欲操作本对象>.at(@<索引值>)
    }

    方法 添加 <公开 静态 类型 = 整数 @嵌入式方法 = "">
    参数 欲操作本对象 <类型 = Ac数组类>
    参数 值 <@匹配类型 = 所有类型>
    {
      @ @<欲操作本对象>.append(@<值>)
    }

    方法 移除子数组 <公开 静态 @嵌入式方法 = "">
    参数 欲操作本对象 <类型 = Ac数组类>
    参数 起始索引 <类型 = 整数>
    参数 结束索引 <类型 = 整数>
    {
      @ @<欲操作本对象>.removeSubArray(@<起始索引>,@<结束索引>)
    }

    #
}
<火山程序 类型 = "通常" 版本 = 1 />

类 AcDb对象ID数组 <公开 基础类 = Ac数组类 @别名 = "AcDbObjectIdArray" @模板实现类 = "AcDb对象ID数组">
{

    #
}
对应封装的原生代码如下:







Xelloss0618 发表于 2025-2-17 23:48:22

这个报错是内存操作的问题,跟你那些封装没关系,一般是因为你有代码重复释放内存了。

沉默流星 发表于 2025-2-18 08:03:56

Xelloss0618 发表于 2025-2-17 23:48
这个报错是内存操作的问题,跟你那些封装没关系,一般是因为你有代码重复释放内存了。
...

我把火山生成的这部分C++代码移植到用VS的源项目函数中去,进行DEBUG并没有报错。
操作gif如下:

沉默流星 发表于 2025-2-18 09:09:17

这是VS原项目例子代码:
#include "stdafx.h"
#include <dbcurve.h>
//#include <dbregion.h>
#include "dbregion.h"
#include "CRegionUtil.h"
#include "CDwgDatabaseUtil.h"
AcDbObjectIdArray CRegionUtil::Add(const AcDbObjectIdArray& curveIds)
{
        AcDbObjectIdArray regionIds;        // 生成的面域的ID数组 acgeoment.lib
        AcDbVoidPtrArray curves;                // 指向作为面域边界的曲线的指针的数组
        AcDbVoidPtrArray regions;                // 指向创建的面域对象的指针的数组
        AcDbEntity* pEnt = NULL;                                // 临时指针,用来关闭边界曲线
        AcDbRegion* pRegion = NULL;                // 临时对象,用来将面域添加到模型空间

        // 用curveIds初始化curves
        for (int i = 0; i < curveIds.length(); i++)
        {
                acdbOpenAcDbEntity(pEnt, curveIds.at(i), AcDb::kForRead);
                if (pEnt->isKindOf(AcDbCurve::desc()))
                {
                        curves.append(pEnt);
                        //curves.append(static_cast<void*>(pEnt));
                }
        }

        Acad::ErrorStatus es = AcDbRegion::createFromCurves(curves, regions);
        if (es == Acad::eOk)
        {
                // 将生成的面域添加到模型空间
                for (inti = 0; i < regions.length(); i++)
                {
                        // 将空指针(可指向任何类型)转化为指向面域的指针
                        //pRegion = static_cast<AcDbRegion*>(regions);
                        pRegion = (AcDbRegion*)(regions);
                        pRegion->setDatabaseDefaults();
                        AcDbObjectId regionId;
                        AcDbDatabase* sjk = NULL;
                        regionId = CDwgDatabaseUtil::PostToModelSpace(pRegion,sjk);
                        regionIds.append(regionId);
                }
        }
        else        // 如果创建不成功,也要删除已经生成的面域
        {
                for (int i = 0; i < regions.length(); i++)
                {
                        delete (AcRxObject*)regions;
                       
                }
        }

        // 关闭作为边界的对象
        for (int i = 0; i < curves.length(); i++)
        {
                //pEnt = static_cast<AcDbEntity*>(curves);
                pEnt=(AcDbEntity*)(curves);
                pEnt->close();
        }

        return regionIds;
       
}

#include "stdafx.h"
//#include "StdArx.h"
#include "创建面域.h"
#include "CRegionUtil.h"
void ZffChap2AddRegion()
{
        // 使用选择集,提示用户选择作为面域边界的对象
        ads_name ss;
        int rt = acedSSGet(NULL, NULL, NULL, NULL, ss);                // 提示用户选择对象       

        // 根据选择集中的对象构建边界曲线的ID数组
        AcDbObjectIdArray objIds;
        if (rt == RTNORM)
        {
                //long length;书籍中有错误
                int length;
                acedSSLength(ss, &length);                // 获得选择集中的对象个数
                int i = 0;
                for ( i = 0; i < length; i++)
                {
                        ads_name ent;
                        acedSSName(ss, i, ent);
                        AcDbObjectId objId;
                        acdbGetObjectId(objId, ent);

                        objIds.append(objId);
                }
        }
        acedSSFree(ss);                        // 及时释放选择集



        AcDbObjectIdArray regionIds;
        regionIds = CRegionUtil::Add(objIds);

        int number = regionIds.length();
        acutPrintf(L"\n已经创建%d个面域.", number);

       
}
void 创建面域::创建面()
{
        //addCommand 5个参数注解:命令组名称、国际名称、本地化名称、命令的类型和指向实现函数的指针
        acedRegCmds->addCommand(L"pch", L"Hello", L"椭圆", ACRX_CMD_MODAL, ZffChap2AddRegion);
}
这是火山按VS代码写的如下:

--

--

--

--



static/image/hrline/1.gif
这是火山项目转成VS项目之后,进行调试报错的过程。
过程gif

Xelloss0618 发表于 2025-2-18 11:54:07

你 ads_name 的别名类型是「本地结构」?我看到有个内存清零的操作。
「本地结构」这个别名类型,只适合纯C的结构体。
如果是C++的结构体,里面有构造函数、析构函数和成员方法之类的,必须用「本地类」。

沉默流星 发表于 2025-2-18 12:10:38

Xelloss0618 发表于 2025-2-18 11:54
你 ads_name 的别名类型是「本地结构」?我看到有个内存清零的操作。
「本地结构」这个别名类型,只适合纯C ...
ads_name的类型是本地值类型是你给我写个那个就是这个帖子:
【已解决】类型无法强转如何封装 - 火山平台俱乐部 - 递归火山软件开发平台 - Powered by Discuz!

沉默流星 发表于 2025-2-18 12:28:11

Xelloss0618 发表于 2025-2-18 11:54
你 ads_name 的别名类型是「本地结构」?我看到有个内存清零的操作。
「本地结构」这个别名类型,只适合纯C ...

我怕是因为这段是因为我封装的问题,所以进制注释了。
然后进行嵌入的,但也是d e b u g的在c a d中蹦掉

static/image/hrline/1.gif
下面是项目源码

沉默流星 发表于 2025-2-18 19:28:29

頂一下

沉默流星 发表于 2025-2-18 21:02:38

1.使用vs模板创建的项目,写的代码调试和编译都没问题
2.使用火山封装的代码当前这个例子调试的话cad会蹦,但编译的没有问题
3.使用火山把当前例子代码需要的部分不封装,只把代码使用@字符进行嵌入,调试版cad崩溃,编译版没有问题
4.使用火山生成的当前例子部分的c++代码,移植到vs原项目函数中,调试和编译没有任何问题
5.使用火山调试之后生成c++代码,把这个代码使用大色秘密的火山转vs工具转换之后,调试崩溃,编译没问题。停止位置是微软的断言头文件,并没有断到出现错误的位置
页: [1] 2
查看完整版本: 为什么调试版报错