什么时候在 Excel XLL 中释放 FP * 是安全的?

Posted

技术标签:

【中文标题】什么时候在 Excel XLL 中释放 FP * 是安全的?【英文标题】:When is it safe to free a FP * in a Excel XLL? 【发布时间】:2011-10-10 11:25:06 【问题描述】:

MSDN states:

... 因此,当返回 DLL 创建的字符串或浮点数时 数组,您有以下选择:

设置一个指向动态分配缓冲区的持久指针,返回指针。在下一次调用函数 (1) 时,检查 指针不为空,(2)释放上一个分配的资源 调用并将指针重置为空,(3)将指针重用于新的 分配的内存块。 ...

当我拨打免费电话时,我收到以下错误对话框:

MSVC++ 调试库 HEAP CORRUPTION DETECTED: 正常后 block(#135) at 0x....... CRT 检测到应用程序写入 修复缓冲区结束后的内存。

这是我的代码:

FP * g_FP;

extern "C" FP * __stdcall xllFill(long rows, long cols) 

    if (g_FP != NULL) 
        free(g_FP);
        g_FP = NULL;
    
    g_FP = (FP *)malloc(rows * cols * sizeof(double) + 2 * sizeof(unsigned short int));

    for (int i = 0; i < rows * cols; i++) 
        (*g_FP).data[i] = (double)i;
    
    (*g_FP).rows = (unsigned short int)rows;
    (*g_FP).cols = (unsigned short int)cols;
    return g_FP;

我对 C++ 有点生疏,但我一辈子都想不通为什么这不起作用。

【问题讨论】:

你有没有在释放 g_FP 之前初始化它如果没有,你释放了一个野指针。 @San Jacinto 它被声明为全局并且将被初始化为 NULL。通过 IMV 明确地这样做会更好。 更准确地说,它具有静态存储持续时间,因此将被零初始化。但是,系统上的NULL 指针不一定具有字节值“0”(即使我们写了void* ptr = 00 不一定是磁盘上的值)。你应该写FP* g_FP = 0;FP* g_FP = NULL; @TomalakGeret'kal: [dcl.init] ¶5: "如果 T 是标量类型 (3.9),则将对象设置为值 0(零),作为整数常量表达式,转换为T" - 我认为这意味着零初始化完全等同于FP* g_FP = (FP*)0;,因此您对实际字节值的考虑不应该在这里适用(尽管我更喜欢显式初始化全局变量) . @Matteo:哦,嗯……好吧,我同意。 :) 【参考方案1】:

FP 声明如下:

typedef struct _FP

    unsigned short int rows;
    unsigned short int columns;
    double array[1];        /* Actually, array[rows][columns] */
 FP;

您假设FP 已打包并且不包含填充。我不知道如何编译 XLL,但我认为 columnsarray 之间很可能存在填充,以安排 array 是 8 字节对齐的。在默认设置下,MSVC 为 sizeof(FP) 返回 16,这支持了我的假设。

将您的分配更改为:

g_FP = malloc((rows*cols-1)*sizeof(double) + sizeof(*g_FP));

即使这不是问题的原因,上面的分配也是逻辑上正确的形式。

否则我看不出你的代码有什么问题。我认为您可以更明确地将g_FP 初始化为NULL,但这是次要的。

【讨论】:

正是我的分析。很多谢谢(虽然我认为你比我按发送键一分钟;o)) 谢谢。实际上,我在 11 分钟之前就拥有了你! ;-) 顺便说一句,如果rows*cols 的新值大于以前的值,我认为我只会执行free/malloc。这样可以节省更多地使用堆分配器。 我的浏览器告诉我有一个答案,而我正在写它;o)。反正有点尴尬!!! 一点也不尴尬。我们都做这样的事情。【参考方案2】:

sizeof(FP) 是 16,因为行和列最终对齐(大概)。我不允许在我的手动尺寸计算中这样做。

更好的代码是:

g_FP = (FP *)malloc(sizeof(sizeof(FP) - sizeof(double) + rows * cols * sizeof(double)); // -sizeof(double) to account for the double[1] already in the struct def.

【讨论】:

【参考方案3】:

省点麻烦,使用http://nxll.codeplex.com 中的 FP 类。它的文档是http://nxll.codeplex.com/wikipage?title=FP。

【讨论】:

以上是关于什么时候在 Excel XLL 中释放 FP * 是安全的?的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 UDF .xll 在 HPC 网格上并行化 Excel

如何从 R 调用 Excel UDF (*.XLL) 函数

Excel催化剂开源第2波-自动检测Excel的位数选择对应位数的xll文件安装

为 ExcelDna .xll 插件加载自定义功能区

从 XLL 函数返回 unicode 字符串

Excel 自定义函数