【发布时间】:2017-06-20 13:07:16
【问题描述】:
我对如何在 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;
}
【问题讨论】:
-
有什么理由要在 c 中模拟对象吗? c++不是更容易吗?
-
我根本不会使用 malloc/free,主要是因为 malloc/free 是相当昂贵的操作,性能较低。
-
只是一个旁注。我怀疑您正在实施四元数以在可能对性能敏感的事情上进行数学运算。不断的 malloc 绝对会破坏你的表现。如何避免内存泄漏和同时不破坏性能的一个不错的答案是:不要 malloc。不惜一切代价避免使用 malloc,让用户处理分配和释放。
-
我要告诉你一件事,你的指针间距让你很难调试,就像
this->x*p->y这样的乘法一样。您已将空间放在不属于它们的位置,并将它们从它们所在的位置删除。您希望在视觉上关联事物以提高清晰度,而不是将事物塞在一起。一般除指针外,运算符两边都有空格(一个空格)。 -
为了让它看起来正确,我做了太多的编辑,但我现在已经完成了答案。
标签: c pointers object struct memory-leaks