使用指向第一个成员的指针调用 free 是不是有效?

Posted

技术标签:

【中文标题】使用指向第一个成员的指针调用 free 是不是有效?【英文标题】:Is it vali to call free with a pointer to the first member?使用指向第一个成员的指针调用 free 是否有效? 【发布时间】:2016-08-04 13:47:31 【问题描述】:

是否可以在指向结构的第一个成员的指针上调用 free(并且该结构是与 malloc 相关的结构)?我原则上知道指针指向正确的东西......

struct s int x;;
//in main
struct s* test;
test = (struct s*) malloc(sizeof(*test));
int* test2;
test2 = &(test->x);
free(test2); //is this okay??

另外,如果int x 被替换为结构体,答案会改变吗?

更新:我为什么要编写这样的代码?

struct s int x;;
struct sx1 struct s test; int y;; //extending struct s
struct sx2 struct s test; int z;; //another
// ** some functions to keep track of the number of references to each variable of type struct s 
int release(struct s* ptr)
  //if the number of references to *ptr is 0 call free on ptr

int main()
    struct sx1* test1;
    struct sx2* test2;
    test1 = (sx1*) malloc(sizeof(*sx1));
    test2 = (sx2*) malloc(sizeof(*sx2));
    //code that changes the number of references to test1 and test2, calling functions defined in **
    release(test1);
    release(test2);

【问题讨论】:

@user71815 我认为没有必要,最好编译和检查。 (然后让我们知道) 你为什么要写这样的代码? 这绝对是一件奇怪的事情。我永远不会写这样的代码。为什么不直接释放原始指针,而不是尝试从结构成员的地址推断它? @TomKarzes 是的 - 当有人在开始时推入另一件事会发生什么? "如果已经问过这个问题,请删除它。"不会。几年后其他人可能会发现它很有用。 【参考方案1】:

根据 C11 标准,第 §6.7.2.1 章

[...] 可能有未命名的 在结构对象内填充,但不在其开头。

这意味着结构的开头不能有任何填充。因此,第一个成员的地址与结构变量的地址相同。

free() 需要一个以前由 malloc() 或家人返回的指针。

在您的情况下,您传递的地址与 malloc() 返回的地址相同。所以,你很高兴。

【讨论】:

【参考方案2】:

是的,没关系。

6.7.2.1

    在结构对象中,非位域成员和位域所在的单元 驻留的地址按照它们被声明的顺序增加。 指向 a 的指针 适当转换的结构对象指向其初始成员(或者如果该成员是 位域,然后到它所在的单元),反之亦然。可能有未命名的 在结构对象内填充,但不在其开头。

这意味着这是定义的:

struct s int x;;
struct s* test;
test = (struct s*) malloc(sizeof(*test));
int* p = &(test->x);
free(p);

【讨论】:

是的,从某种意义上说,行为是由标准定义的并且可能是预期的,这是可以的。但是,不,从某种意义上说,它 OK,因为它是一种糟糕的风格,因为如果结构定义被修改,它会为以后令人惊讶的失败开辟道路。 该标准不保证指向一种类型的指针与指向另一种类型的指针相同,char * 除外。因此,不,这是不好。它恰好适用于(几乎)所有最近的实现,因为它们使用统一的地址空间。 即使sp这两个指针大小不同、对齐方式不同、表示不同,它们仍然指向同一个地址和同一个对象,因此使用要么释放内存是严格符合的。 它们绝对不会指向同一个对象。原因应该很清楚:类型不同。我和你一起讨论地址。 7.22.3.3p2 也是相关的。考虑到与void * 之间的转换,您似乎是对的,但它是允许的。我仍然认为这是不好的做法,并且可能会混淆静态代码检查器。无论如何,我撤回我的反对意见,但你的回答应该有更多的信息。 @Olaf:获取结构第一项的地址相当于将该结构的地址转换为该类型。该操作在某些实现上可能涉及更改指针的位表示,但如果从 malloc 返回的非空 void* 开始,则通过任何指针数据类型序列转换指针并返回 void* 是保证产生原始指针。

以上是关于使用指向第一个成员的指针调用 free 是不是有效?的主要内容,如果未能解决你的问题,请参考以下文章

求助 一个指针被free之后啥时候是NULL?还是不可能是NULL?

c++“cv::Mat::row”: 函数调用缺少参数列表;请使用“&cv::Mat::row”创建指向成员的指针?

指向实例的成员函数而不是类的指针

关于C语言free函数的问题

C++|详解类成员指针:数据成员指针和成员函数指针及应用场合

malloc必须有对应的free