1

リンクリストを学習中ですが、文字列を解放したときの動作の変化を理解していません。コードは次のとおりです。

#include <stdio.h>
#include <stdlib.h>

struct node {
    char*          data;
    struct node*   next;
    };

void Push(struct node** headRef, char *data)
{
    struct node* newNode = malloc(sizeof(struct node));
    newNode->data = data;
    newNode->next = *headRef;  // The '*' to dereferences back to the real head
    *headRef = newNode;        // ditto
}

int main(int argc, const char * argv[])
{

    char* auxStr;
    struct node* list;
    struct node* auxPtr;
    int i=5;


    while (i<9)
    {
        auxStr=malloc(sizeof("String:%d"));
        sprintf(auxStr, "String:%d",i);
        Push(&list, auxStr);
        i++;
    }

    auxPtr=list;

    i=0;
    while (auxPtr)
    {
        printf("Node:%d - Data:%s\n",i++,auxPtr->data);
        auxPtr=auxPtr->next;
    }

    return 0;
}

その結果、次のようになります。

Node:0 - Data:String:8
Node:1 - Data:String:7
Node:2 - Data:String:6
Node:3 - Data:String:5

今、私が最初の間にfree(auxStr)を追加すると:

while (i<9)
{
    auxStr=malloc(sizeof("String:%d"));
    sprintf(auxStr, "String:%d",i);
    Push(&list, auxStr);
    free(auxStr);
    i++;
}

私は今得ます:

Node:0 - Data:String:8
Node:1 - Data:String:8
Node:2 - Data:String:8
Node:3 - Data:String:8

誰かが理由を説明できますか?私はそれが何度もそこで解放される最も効率的なコードではないかもしれないことを知っています、しかし私はこの振る舞いを見ました、そしてそれは私を困惑させています。私が概念をよりよく理解するのを手伝ってくれるあなたの助けをいただければ幸いです。

ありがとう

4

4 に答える 4

2

未定義の動作が発生しています。

メモリ ( ) を解放していますが、関連するノードauxPtrの のように、メモリへのポインタがまだ残っています。dataこれは、ダングリング リファレンスと呼ばれます。

このデータで何が起こるかは未定義であり、たまたま新しい割り当てごとに同じアドレスを再利用しています (ただし、繰り返しますが、何でも起こり得ます)。

したがって、後でデータを印刷する場合、出力は未定義です。

于 2013-02-03T09:10:17.240 に答える
0

strncpy でデータ文字列をコピーするのではなく、後で解放する同じ文字列にポインターを割り当てるだけです。

于 2013-02-03T09:10:59.463 に答える
0

here で示されているように、解放後にポインターにアクセスすることは未定義の動作です。

于 2013-02-03T09:11:13.650 に答える
0

struct node同じ住所のポイント単位の各データ。を解放auxPtrすると、もう割り当てられていないメモリ位置にアクセスしています。C では、未定義の動作につながります。次のように、データを動的に割り当てることをお勧めします。

#include <assert.h>
#include <stdlib.h>
#include <string.h>

void Push(struct node **head, const char *data, size_t size)
{
  struct node *elt;

  elt = malloc(sizeof *elt);
  assert(elt != NULL);

  elt->data = malloc(size);
  assert(elt->data != NULL);
  memcpy(elt->data, data, size);

  elt->next = *head;
  *head = elt;
}

さらに、リストに null ポインターはありません。list最初に割り当てる必要があります。

于 2013-02-03T09:11:52.633 に答える