2

ll_printを呼び出すと、プログラムが正しくクラッシュする理由を理解しようとしています。[[これは非常に単純でわかりやすい質問です。説明のギャップを埋めるために実際に何を追加すればよいかわかりません]]

    struct ll{
          struct ll* next;
          int n;
        } ll;

   void ll_print(struct ll *l){
      while (l) {
        printf("%d ", l->n);
        l=l->next;
      }
    }

    void ll_fill(struct ll *l, int n){
      struct ll *temp= NULL;
       while (n>0){
        l= (struct ll*)malloc(sizeof(struct ll));
        l->n=n;
        l->next= temp;
        temp=l;
        n--;
      }
     }

    int main(void){
      int i=0;
      struct ll *l;                                                                                                                                          
      ll_fill(l, 10);
      ll_print(l);  /** causing a segmntation fault **/                                                                                                                                                                 
    }
4

6 に答える 6

5

これは、lポインタが初期化されないために発生します。あなたはそれを初期化することを期待しているようですが、あなたは間違っています-それは値によって渡されています(読み取り-コピーによって)、そしてあなたが関数で割り当てるものはll_fill何でも内部で宣言されたものに値を割り当てません。目的を達成するには、ポインターを渡します(ポインターへのポインターがあります)。または、との戻り値にします。また、デバッガーを入手してください。これは非常に役立ちます。lll_filllmainlll_filll = ll_fill(l, 10);

于 2012-07-15T06:29:10.387 に答える
1

l関数内のローカル変数へのポインターを設定していませんmain()l代わりに、関数にの引数を入力していますll_fill()ll_fillmallocされたポインタの値を返すことを検討してください。

于 2012-07-15T06:29:28.640 に答える
1

あなたが電話するときll_fill(l, 10);-あなた自身に尋ねてください、の価値はl何ですか?呼び出された関数内に新しいオブジェクトを作成しますmain()が、その新しいオブジェクトをどのように知っていますか?それはまだあなたのローカル変数に最初に(ランダムに)割り当てられた初期化されていないメモリを指していますl

NULLに初期値としてを割り当ててみてくださいl

struct ll *l = NULL;
于 2012-07-15T06:33:24.463 に答える
1

コールバイバリューの概念に混乱しているだけです。関数ll-fillに値渡しでポインターを渡します。ただし、ll-fillは独自のコピーを作成し、どのような変更を加えても、main関数のポインターには影響しません。したがって、それをll_print()に渡す場合、初期化されていないため、値を出力するとセグメンテーション違反が発生します。
デバッガーを使用すると、常にそのような状態で役立ちます。

于 2012-07-15T06:45:28.273 に答える
1

関数内でポインタlにメモリを割り当てるため、ポインタ変数を渡す代わりに、ポインタのアドレスを渡す必要があります。ポインタlは関数内で初期化されますがll_fill、スコープが関数から出たときにスコープがll_print(l)停止し、ポインタのアドレスが見つからなかったためにセグメンテーション違反がスローされますl

解決 :

  1. 関数内で初期化する場合は、ポインタのアドレスを渡します。

  2. ポインタが複数の関数で共有されている場合は、両方の関数の共通のスコープで宣言することをお勧めします(つまり、内で初期化するmain()) 。

于 2012-07-15T08:15:50.270 に答える
1

ll_fill関数の定義を変更し、次のように呼び出します。

void ll_fill(struct ll **l, int n){
  struct ll *temp= NULL;
  while (n>0){
    *l= (struct ll*)malloc(sizeof(struct ll));
    (*l)->n=n;
    (*l)->next= temp;
    temp=(*l);
    n--;
  }
}

int main(void){
  int i=0;
  struct ll *l;                                                                 
  ll_fill(&l, 10);
  ll_print(l);  /** now no segmntation fault :) **/                             
}
于 2012-07-15T10:43:48.393 に答える