2017-02-03 4 views
3

漏れたが、私はメモリリークが発生しやすい方法からオブジェクトを返すことを事実であるとこのような議論のリストで参照していますか?オブジェクトのメソッド:たとえば、決してオブジェクトを返さない、よりメモリは私がきちんとC.</p> <p>内のオブジェクトを実装する方法について質問がある

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; 
} 
+0

あなたがCでオブジェクトをエミュレートしたい理由はありますか? C++は簡単ではありませんか? –

+0

malloc/freeはかなり高価な操作なので、主にパフォーマンスが低いため、malloc/freeを使用しません。 –

+1

ただのコメントです。私はパフォーマンスの影響を受けやすいかもしれない何かで数学をするために四元数を実装していると思う。定数mallocsはあなたのパフォーマンスを絶対に破壊します。メモリリークを回避し、同時にパフォーマンスを破壊しないようにするには、mallocを使用しないでください。すべてのコストをかけてmallocを避け、ユーザーが割り当てと解放を処理できるようにする。 – Art

答えて

3

実際には、いくつかの機能が何かを更新する副作用の両方を持っている場合でも悪化し、新しく構築された値を返すことができます。言っておけば、scanfは値を返します。

私は次が1つの合理的な解決策であることをお勧めしたいGNU Multi Precision Arithmetic Libraryを見ると(実際には、彼らはメモリ割り当て、ユーザーの頭痛を行うことでさらに行く、ないライブラリの):

  1. だけコンストラクタは、新しいオブジェクトを作成することができます。また、すべてのコンストラクターの名前は同じパターンに従うことをお勧めします。
  2. デストラクタのみが、既存のオブジェクトを破棄できます。
  3. 機能は次のように、(前のオブジェクトにあったすべてのものを上書きし、その結果を置くために)の両方の入力引数(たとえば、+の両側)と出力引数を取る:

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

このようにして、オブジェクトがいつ生成/破壊されたかを常に明確に確認し、漏れや二重解放がないことを保証することができます。もちろん、複数の操作を連鎖させることを防ぎ、中間結果の一時変数を手動で管理することができます。しかし、コンパイラでさえ、動的に割り当てられた変数の寿命についてあまり知りませんので、Cで手動で行う必要があると思います。

実際には、 "ライブラリはメモリを管理しません"という句を追加すると、(ライブラリの観点から見れば)さらにエラーを起こしやすいソリューションが得られます。ライブラリのユーザーは必要に応じてメモリを管理する必要があります。あなたはまた、良い事のようなmalloc/freeメモリ割り当てでユーザーをロックしないようにそのように。

1

あなたのクォータションを動的に割り当てる必要はありません。四元数は固定サイズなので、単純な四元数を使うことができます。整数計算を行う場合は、intのスペースを動的に割り当てることなく、ちょうどintを使用します。 malloc/free(未テストコード)を使用していないため

アイデア

Quaternion quaternion_create(float nw, float nx, float ny, float nz) { 
    Quaternion q; 

    q.w = nw; 
    q.x = nx; 
    q.y = ny; 
    q.z = nz; 
    return 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 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); 

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

そこには可能なメモリリークがなく、パフォーマンスが良くなるので、全くmalloc Sもfree sはありません。

+0

これは良いアプローチです! – clearlight

+0

うわー、これは私が考えなかったことです...私はエレガントな方法があることを知っていました。私はスケーラビリティによってこの問題が発生する可能性のある問題を今でも見ることができません。 – Angel

+0

Destructor?... Quaternion構造体のメンバの1つが、いくつかの配列または構造体へのポインタであるときに、たぶんコードを持つでしょうか? – Angel

1

あなたは間違っているように見えます。

また、malloc()がNULLを返して、そのエラーを処理する必要があるかどうかを確認する必要があります(メモリ不足のエラーメッセージを表示し、一般的には回復できないために失敗した場合など)。

UPDATE:

YOUは、あなたがポインタを保持するために、より多くのアクションを取る必要があり、あなたの中間結果を解放する必要があるため。

UPDATE 2

@MichaelWalzアプローチが素晴らしいです。あなたがする必要がない場合は、なぜすべての割り当てとポインタ管理を扱うのですか?しかし、の場合はポインタを使用してメモリを割り当ててください。ポインタを保持して、物事を自由にして周りをパスしてください。ネストされた呼び出しを処理するために私の例を更新しました。

UPDATE 3

あなたはすでにあなたがポイントにしたいもののアドレスです内のポインタを、渡しているので、私は、関数呼び出しの引数から&年代を削除する必要がありました。関数の出力を適切に割り当てていませんでした。固定の例でも、ポインタの割り当てがどのように異なっているかに注目してください。


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 *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); 


Quaternian *tmp = quaterion_get_product(p, q); 
quaternian_destroy(p); 
p = tmp; 
tmp = quaternion_get_product(s, r) 
Quaternion *t = quaternion_get_product(q, tmp); 
quaternian_destroy(tmp); 
+0

ugh。 ..私はいくつかの試行を取ったが、私は例があなたの使用例に基づいて何をしたいかをもっと考えていると思う。 – clearlight

関連する問題

 関連する問題