C语言接口与实现创建可重用软件的技术读书笔记(5)---内存管理

感觉这章主要就是在将如何对标准C库中malloc,calloc,realloc,和free函数进行封装,重新组织成Mem接口,还有就是对它们运行已检查的错误的跟踪和报告。

所有非平凡的C程序都会在运行时分配内存。标准C库提供了4个内存管理例程:malloc,calloc,realloc,和free。Mem接口将这些例程重新包装为一组宏和例程,使之不那么容易出错,并提供了一些额外的功能。

1、如

p=malloc(nbytes);

...

free(p);

调用malloc分配nbytes长的内存块,将该内存块第一个字节的地址赋值给p,使用p和它指向的内存块,最终释放该内存块。在调用free之后,p包含一个悬挂指针---指向逻辑上不存在的内存的指针。接下来反引用p是一个错误,但是如果该内存块没有因其他原因而再次分配出去,这个错误可能不会被检测到。这种行为时使得此类内存访问错误难于诊断的原因:在检测到错误时,错误暴露的时间和位置可能与错误的来源距离颇远。

2、Mem接口中的宏和例程针对上述各种内存管理错误提供了一些保护。但是它们不能消除所有这些错误。例如,它们无法防止反引用已破坏的指针或者使用指针指向超出作用域的局部变量。C语言初学者经常犯后一个错误,下面给出一个例子:

char *itoa(int n)

{

char buf[43];

sprintf(buf,"%d",n);

return buf;

}     /*itoa返回其局部数组buf的地址,但在itoa返回后,buf就不再存在了。*/

3、Mem接口提供了宏,将内存分配和赋值封装起来:

#define NEW(p) ((p)=ALLOC((long)sizeof *(p)))

#define NEW0(p) ((p)=CALLOC(1,(long)sizeof *(p)))

NEW(p)分配了一个未初始化的内存的内存块以容纳*p,并p设置为该块的地址。NEW0(p)完成的工作类似,还将内存块清零。提供NEW时有下述假设:大多数客户程序在分配内存块后会立即初始化。传递给编译时运算符sizeof的参数只是用于获取其类型,运行时不会计算其值。因此NEW和NEW0只会计算p一次,使用具有副效应的表达式作为这两个宏的实参是安全的,例如NEW(a[i++])。


4、例程将对标准库中内存管理函数的调用封装到通过Mem接口规定的更安全的软件包中。(malloc,calloc,realloc,和free)

#include<stdlib.h>

#include<stddef.h>

#include"assert.h"

#include"except.h"

#include"mem.h"

const Except_T Mem_Failed={" Allocation Failed"};


①Mem_alloc调用malloc,并在malloc返回NULL指针时引发Mem_Failed异常:

void    *Mem_alloc(long nbytes, const char  *file,int line)

{

void *ptr;

assert(nbytes>0);

ptr=malloc(nbytes);

if(ptr==NULL)

{

if(file==NULl)

{

RAISE(Mem_Failed);

}

else

{

Except_raise(&Mem_Failed,,file,line);

}

}

}

②在count或nbytes为零时,calloc的行为是由具体实现定义的。

void  *Mem_calloc(long count, long nbytes, const char  *file, int line)

{

void  *ptr;

assert(count>0);

assert(nbytes>0);

ptr=calloc(count, nbytes);

if(ptr== NULL)

{

if(file==NULl)

{

RAISE(Mem_Failed);

}

else

{

Except_raise(&Mem_Failed,,file,line);

}

}

return ptr;

}

③Mem_resize的规格说明比realloc简单得多。Mem_resize唯一的目的就是改变某个现存内存块的长度。realloc也完成了同样的工作,但是它在nbytes为零时会释放内存块,而在ptr是NULL指针时会分配内存块。这些额外的功能与修改现存内存块的长度只有松散的关联,很容易引入bug。

void  *Mem_resize(void  *ptr, long nbytes, const char *file, int line)

{

assert(ptr);

assert(nbytes>0);

ptr=realloc(ptr,nbytes);

if(ptr==NULL)

{

if(file==NULl)

{

RAISE(Mem_Failed);

}

else

{

Except_raise(&Mem_Failed,,file,line);

}

}

return ptr;

}

void Mem_free(vid  *ptr, const char *file, int line)

{

if(ptr)

free(ptr);

}

5、分配函数从来不返回同一地址两次的条件,可以通过从不释放由分配函数返回的内存块。通过维护一个保存这种内存块地址的表,即可实现集合S。

这种方案的内存分配器,可以基于标准库函数实现。该分配器维护了块描述符的一个哈希表。

static struct descriptor

{

struct descriptor *free;

struct descriptor *link;

const void *ptr;

long size;

const char *file;

int line;

} *htab[2048];

ptr是块的地址,在代码中其他地方分配,size是块的长度。file和line是该块的分配“坐标”,即客户程序中调用相关分配函数的源代码所处的位置(也会作为参数传递给分配函数)。这些值并不使用,但会保存在描述符中,以便调试器在调试会话期间输出相关信息。

Mem_alloc使用最先适配算法分配内存,这是诸多内存分配算法之一。它会搜索freelist来查找第一个能够满足请求的足够大的空闲块,并划分该块来满足请求。如果freelist不包含适当的块,Mem_alloc调用malloc分配比nbytes大的一个内存块,将该块添加到空闲链表,然后再次尝试。因为新的内存块不nbytes大,这一次将使用该块来满足请求。









### 回答1: 将DBCExcel格式互相转换是一种常见的数据处理需求。 首先,我们来说DBCExcelDBC文件是一种常用于汽车行业的数据格式,通常包含了汽车诊断故障码、传感器数据等信息。要将DBC转换为Excel,我们可以使用一些专业的工具,如CANoe或Vector CANdb++。 1. 使用CANoe进行DBCExcel: a. 在CANoe中打开DBC文件。 b. 选择要导出的信号和数据。 c. 通过导出功能将数据导出为Excel文件。 2. 使用Vector CANdb++进行DBCExcel: a. 在CANdb++中打开DBC文件。 b. 选择要导出的信号和数据。 c. 通过导出功能将数据导出为Excel文件。 现在,我们来说ExcelDBCExcel是一种常见的办公软件,可以轻松创建、编辑和管理数据表。如果要将Excel转换为DBC,我们可以使用一些特定的软件工具。 1. 使用CANoe进行ExcelDBC: a. 在CANoe中创建一个新的DBC文件。 b. 导入Excel数据表格。 c. 将Excel数据映射到DBC中的信号和数据。 d. 导出DBC文件。 2. 使用Vector CANdb++进行ExcelDBC: a. 在CANdb++中创建一个新的DBC文件。 b. 导入Excel数据表格。 c. 将Excel数据映射到DBC中的信号和数据。 d. 导出DBC文件。 需要注意的是,在转换过程中,需要按照DBC定义的格式和规范进行设置和映射,以确保转换后的文件保持一致性和准确性。 总结起来,DBCExcel之间的相互转换需要使用专业的工具和软件,根据具体的需求和文件格式,进行相应的设置和映射,以实现转换。 ### 回答2: DBC是一种二进制文件格式,用于存储数据方面的信息,特别是用于存储芯片或设备的控制参数。而Excel是一种电子表格软件,用于存储和处理数据。虽然这两种文件格式有着不同的用途和结构,但是我们可以通过一些方法将DBC文件和Excel文件互相转换。 要将DBC文件转换为Excel文件,可以借助一些软件或工具。首先,我们可以使用CAN分析工具来打开DBC文件,然后将数据导出为CSV或文本文件。接下来,可以使用Excel打开导出的CSV文件,并对数据进行进一步的处理和格式化,以满足需求。 另一种方法是使用专门用于DBC文件和Excel文件转换的工具。这类工具通常具有用户友好的界面和丰富的功能,可以直接将DBC文件转换为Excel文件,而无需进行额外的操作和处理。用户只需选择要转换的DBC文件,然后设置一些参数,即可轻松完成转换过程。 而将Excel文件转换为DBC文件则需要使用相反的方法。首先,可以将Excel文件中的数据保存为CSV或文本文件。然后,可以使用CAN分析工具或专门的转换工具来导入CSV或文本文件,并将其转换为DBC文件。在转换过程中,可能需要设置一些参数,例如信号名称、数据类型和编码方式等。 需要注意的是,转换过程中可能会涉及到数据结构的映射、数据类型的转换和参数设置等问题,因此在进行转换之前,最好对DBC文件和Excel文件的结构和数据进行了解,以确保转换结果的准确性和完整性。此外,还要确保所使用的工具和软件是可信赖的,并遵守相关的使用规定和许可证要求。 ### 回答3: DBCExcel是两种不同的数据格式,有一些工具可以用来实现DBCExcel之间的相互转换。 要将DBC转换为Excel,可以使用一些DBC编辑软件,如Vector CANoe、CANalyzer等。这些软件通常提供了将DBC文件导出为Excel格式的选项。用户可以通过选择导出的信号、消息和节点等信息来自定义导出的Excel文件。从而可以将DBC文件中的信号和消息等数据转换为Excel表格中的行和列数据,方便查看和分析。 要将Excel转换为DBC,可以使用一些DBC编辑工具,如CANdb++等。这些工具通常提供了将Excel文件导入为DBC格式的功能。用户可以将Excel中的数据按照特定的格式,如列名、行名等,进行导入,从而生成相应的DBC文件。 在进行DBCExcel的相互转换时,需要注意数据的准确性和格式的兼容性。另外,不同的工具和软件可能会有一些不同的操作步骤和设置选项,用户在进行转换之前需要先了解和熟悉相应的工具和软件的使用方法。 总之,DBCExcel之间的转换可以通过使用一些DBC编辑软件和工具来实现。这些工具可以将DBC文件导出为Excel格式,或将Excel文件导入为DBC格式,从而方便用户对数据进行查看、编辑和分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值