4

いくつかのメモリ割り当てで、これを見つけました。しかし、私はそれを理解していません。

char * mem_alloc()
{   
    char *point;
    char *a;
    point = (char *)malloc(block_num);

    a = *(char**) point;
    return a;
}   
4

6 に答える 6

8

char * mem_alloc()

私の経験では、ポインターを返す関数は、ほとんどの場合、プログラム設計に欠陥があることを示しています。このようなポインターは、次の場所を指している可能性があります。

  • ローカル変数 (あからさまなバグ、UB)
  • グローバル/静的 (貧弱なプログラム設計であり、スレッドセーフでもない)
  • 動的メモリ (不十分なプログラム設計、メモリを使用するコードが割り当てを処理する必要がある、リークの大きな可能性)
  • または、関数に渡されるパラメーターの 1 つ (プログラムの設計が不十分、関数のインターフェイスがわかりにくい)

この場合、動的メモリを指しているため、プログラムの設計が不十分であり、メモリ リークが発生する可能性が高いと想定できます。

point = (char *)malloc(block_num);

このコードを書いた人は、malloc がどのように機能し、void ポインターがどのように機能するかについて混乱していることを意味します。malloc の結果は決して型キャストされるべきではありません。 thisおよびthisを参照してください。型キャストへの衝動は、プログラマーが C 言語について混乱していること、および/または C++ コンパイラーで C コードをコンパイルしようとしていることを意味します。

「block_num」は疑わしいです。これがグローバルで定数でない変数である場合、プログラムの設計が不十分です。

a = *(char**) point;

これは、ヒープ上の初期化されていないメモリを指しているポイントのアドレスを取得し、そのポイントがポインターツーポインターであると見なして、ヒープのガベージ コンテンツをポインターであるかのように扱うことを意味します。次に、ララランドのランダムな場所を指すこのポインターを呼び出し元に返します。そうしている間に、メモリリークが発生します。

于 2012-06-11T06:48:20.890 に答える
0

Lundin's answer のコメントに投稿されたコード chenyoufu123 を見ると、次のようになります。

ptr = (char *)malloc(block_num * size);
for(k=0; k<block_num-1; k++) {
    *((char **)(ptr + k*size)) = ptr + (k+1) * size;
}
*((char **)(ptr + k*size)) = NULL;

それはまだ悪いコードですが、質問の元のコードのように完全に無意味というわけではありません。特に、別のコメントからリンクされたリストを作成するために使用されるという発言とともに。

状況は、コードが「正しい」と仮定すると、

struct Node
{
    struct Node *next;
    /* More members */
};

およびsize_t size = sizeof(struct Node);(名前はおそらく異なります)。それで

ptr = (char *)malloc(block_num * size);

block_num連続するstruct Nodesにメモリを割り当てます。通常、それを次のように割り当てます。

struct Node *ptr = malloc(block_num * sizeof *ptr);

ループ

for(k=0; k<block_num-1; k++) {
    *((char **)(ptr + k*size)) = ptr + (k+1) * size;
}
*((char **)(ptr + k*size)) = NULL;

k * sizeof(struct Node)次に、メモリ ブロックの先頭の後ろのアドレスptr + k*sizeをポインタへのポインタとして再解釈します (achar**ですが、最近のほとんどの PC アーキテクチャでは、すべてのオブジェクト ポインタが同じ表現を持っているため、これは重要ではありません。重要な場合は、コードが壊れています)。とにかく)、次sizeof(struct Node)のサイズのメモリチャンクのアドレスをその場所に書き込みます。nextポインタは の最初のメンバであるため、リスト内の次のアドレスを現在の のポインタにstruct Node書き込みます。最後に、最後のポインタを に設定します。struct Nodenextstruct Nodenextstruct NodeNULL

普段の書き方ですが、

struct Node *ptr = malloc(block_num * sizeof *ptr);
int k;
for(k = 0; k < block_um - 1; ++k)
{
    ptr[k].next = &ptr[k+1]; // or ptr + (k+1), if you prefer
}
ptr[block_num-1].next = NULL;

char*はより明確であるだけでなく、とstruct Node*が異なるサイズまたは表現を持つプラットフォームで動作するという利点もあります。

于 2012-06-11T10:37:43.557 に答える
0

aが指す位置に格納されている値が含まれpointます。は初期化されていないためpoint、ランダムな値を含むランダムな場所をa指しているため、最初からランダムな値を指しています。

したがって、コードはノーオペレーションです。

于 2012-06-11T05:40:40.793 に答える
0

これは、ポイントの値 (アドレス) を設定するようです。
a = *(char**) point;
上記のステートメントは、「(char**) ポイント」部分の「ポインタへのポインタ」へのポイントを型キャストしています。この後、参照解除用の * が
あり、(ポインターへのポインター)
=> ポインターの値に変更されます。
したがって、ポイントに格納されている値(アドレスではなく)が a にコピーされます。
なぜこの種のコードが書かれているのかはまだわかりません。

于 2012-06-11T05:32:19.673 に答える
0

あなたが投稿したコードはばかげています - 本当に完全ですか?

"point" と "a" はどちらもポインターです。

「a」は「point」に初期化されますが、「point」は完全に初期化されていません。呼び出し元が戻り値「a」を使用しようとすると、悪いことが起こります。

別の例を次に示します。

struct Point {
  int x;
  int y;
};

...

char * mem_alloc (int size)
{
  return (char *)malloc (size);
}

...
  Point *my_point = (Point *)mem_alloc (sizeof (struct Point));
  ...

このスニペットもばかげています...しかし、うまくいけば、あなたが見ているコードの背後にある理論的根拠を少し示しています...

于 2012-06-11T05:34:10.903 に答える
0

の概念を見ると、malloc常に割り当てられたメモリ空間のベース アドレスが返されます。malloc関数の実際の構文は次のとおりです。

pointer_to_store_base_add_of_mem = (data_type_of_allocated_memory)malloc(size_of_array)

上記の例では、メモリの文字型を割り当てたため、(char*) を使用し、block_num で文字配列のサイズを指定し、ポイント ポインタは割り当てられたメモリのベース アドレスを格納します。

于 2012-06-11T08:25:12.553 に答える