gpt4 book ai didi

c - C : memory leaks 中的对象方法

转载 作者:太空狗 更新时间:2023-10-29 16:10:39 25 4
gpt4 key购买 nike

我对如何在 C 中正确实现对象有疑问。

我从方法中返回对象是否比从不返回对象并像这样在参数列表中通过引用更容易发生内存泄漏?

extern void quaternion_get_product(Quaternion * this, Quaternion * q, Quaternion * result);

这样malloc()调用只在构造函数中完成,所以更容易控制。

我对 C 中的这种封装不熟悉,所以我不确定这是否是解决我的问题的方法。我只希望我的代码具有可扩展性,而且我发现如果我继续这样做,内存泄漏将会无处不在,而且调试起来会非常困难。通常如何处理?我的代码是否走在正确的轨道上?

我的问题是,如果我有这个:

Quaternion p = *quaternion_create(1, 0, 0, 0);
Quaternion q = *quaternion_create(1, 0, 1, 0);
Quaternion r = *quaternion_create(1, 1, 1, 0);
Quaternion s = *quaternion_create(1, 1, 1, 1);

p = *quaterion_get_product(&p, &q); // Memory leak, old p memory block is not being pointed by anyone

Quaternion t = *quaternion_get_product(&q, quaternion_get_product(&s, &r));

嵌套函数调用时存在内存泄漏,中间内存块未被任何现有指针指向,无法调用quaternion_destroy

头文件:

#ifndef __QUATERNIONS_H_
#define __QUATERNIONS_H_

#include <stdlib.h>

typedef struct Quaternion Quaternion;

struct Quaternion {
float w;
float x;
float y;
float z;
};

extern Quaternion *quaternion_create(float nw, float nx, float ny, float nz);
extern void quaternion_destroy(Quaternion *q);
extern Quaternion *quaternion_get_product(Quaternion *this, Quaternion *q);
extern Quaternion *quaternion_get_conjugate(Quaternion *this);
extern float quaternion_get_magnitude(Quaternion *this);
extern void quaternion_normalize(Quaternion *this);
extern Quaternion *quaternion_get_normalized(Quaternion *this);
#endif

执行文件:

#include "quaternion.h"
#include <math.h>

Quaternion *quaternion_create(float nw, float nx, float ny, float nz) {
Quaternion *q = malloc(sizeof(Quaternion));

q->w = nw;
q->x = nx;
q->y = ny;
q->z = nz;
return q;
}

void quaternion_destroy(Quaternion *q) {
free(q);
}

Quaternion *quaternion_get_product(Quaternion *this, Quaternion *p) {
Quaternion *return_q = quaternion_create(
this->w * p->w - this->x * p->x - this->y * p->y - this->z * p->z, // new w
this->w * p->x + this->x * p->w + this->y * p->z - this->z * p->y, // new x
this->w * p->y - this->x * p->z + this->y * p->w + this->z * p->x, // new y
this->w * p->z + this->x * p->y - this->y * p->x + this->z * p->w
);
return return_q;
}

Quaternion *quaternion_get_conjugate(Quaternion *this)
{
return quaternion_create(this->w, -this->x, -this->y, -this->z);
}

float quaternion_get_magnitude(Quaternion *this) {
return sqrt(this->w * this->w + this->x * this->x + this->y * this->y + this->z * this->z);
}

void quaternion_normalize(Quaternion *this) {
float m = quaternion_get_magnitude(this);
this->w /= m;
this->x /= m;
this->y /= m;
this->z /= m;
}

Quaternion *quaternion_get_normalized(Quaternion *this) {
Quaternion *r = quaternion_create(this->w, this->x, this->y, this->z);
quaternion_normalize(r);
return r;
}

最佳答案

实际上,如果某些函数具有更新某些内容并返回新构造的值的两种副作用,情况可能会变得更糟。说吧,谁还记得 scanf 返回一个值?

查看GNU Multi Precision Arithmetic Library我建议以下是一个合理的解决方案(实际上,它们更进一步让内存分配用户头疼,而不是图书馆的头疼):

  1. 只有构造函数才能创建新对象。我还建议所有构造函数的名称都遵循相同的模式。
  2. 只有析构函数才能销毁已经存在的对象。
  3. 函数接受两个输入参数(例如,+ 的两侧)和输出参数(将结果放在哪里,覆盖之前对象中的所有内容),如下所示:

mpz_add (a, a, b);/* a=a+b */

这样您将始终清楚地看到对象何时被创建/销毁,并可以确保没有泄漏或双重释放。当然,这会阻止您将多个操作“链接”在一起,并使您手动管理中间结果的临时变量。但是,我相信您仍然需要在 C 中手动执行此操作,因为即使是编译器也不太了解动态分配变量的生命周期。

实际上,如果我们不离开。 3 并添加“库不管理内存”子句,我们将得到更容易出错的解决方案(从库的角度来看),这将要求库的用户随心所欲地管理内存。这样,您也不会使用 malloc/free 内存分配来锁定用户,这是一件好事。

关于c - C : memory leaks 中的对象方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42019535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com