2017-05-07 23 views
0

這個疑問是非常具體的,請考慮下面的代碼 塊中的兩條線是我混淆的線。即。當我交換這兩條線時,出現了分段錯誤,但此代碼仍在運行。因此,我的問題是 當我交換兩條線時發生了什麼?指向一個未初始化的指針vs爲它指定內存後指向它

#include<stdio.h> 
#include<stdlib.h> 
    typedef struct scale_node_s { 
    char note[4]; 
    struct scale_node_s *linkp; 
} scale_node_t; 
int main(){ 
scale_node_t *scalep, *prevp, *newp,*walker; 
int i; 
scalep = (scale_node_t *)malloc(sizeof (scale_node_t)); 
scanf("%s", scalep->note); 
prevp = scalep; 
for(i = 0; i < 7; ++i) { 
    //--------------------------------------- 
    newp = (scale_node_t *)malloc(sizeof (scale_node_t));  
    prevp->linkp = newp; 
    //--------------------------------------- 
     scanf("%s", newp->note); 
    prevp = newp; 
    } 
walker = scalep; 
    for(i = 0 ; i < 7 ; i++){ 
    printf("%s",walker->note); 
    walker = walker->linkp; 
} 


} 
+0

'prevp-> linkp = newp;'複製'newp'的值,它並不指向它 –

回答

1

newp = (scale_node_t *)malloc(sizeof (scale_node_t));分配一塊以保持的scale_node_t實例所需存儲器和使newp保持該地址。在下一行中,您將newp傳遞給一個結構爲linkp的值。
因爲在循環的第一次運行newp被定義,但它的值不確定,它可以保存幾個值取決於操作系統(也可能在編譯器上):內存浪費,或0(所以newp甚至可以是空指針那裏),因此發生分段錯誤。
在初始化之前不允許使用任何變量(指針實際上是變量,將內存地址保存爲數字),但是某些編輯器/環境/編譯器在編譯時可能不會提醒您。

1

除了另一個答案,你還有一些額外的問題,使你的列表邏輯非常混亂和脆弱。首先,您正在對循環迭代進行硬編碼,這些迭代可能會或可能不匹配您的輸入。鏈表的全部用途是提供一個靈活的數據結構,使您可以存儲一個未知的節點數量。 for(i = 0; i < 7; ++i)完全失敗了這個目的。

它是什麼你想存儲?你的意見是什麼? (note字符串)。爲什麼不在輸入有效的note時創建附加節點?它可以是簡單:

char tmp[MAXC] = ""; 
    ... 
    while (scanf ("%3s", tmp) == 1) { 
     ... 
     strcpy (newp->note, tmp); /* set note and linkp */ 
     ... 
    } 

您也留下自己敞開到整個代碼處理無效值。爲什麼?您無法驗證您的用戶輸入和內存分配。如果任一失敗,您將繼續盲目地使用未定義的值。總是驗證所有用戶輸入內存分配。這很簡單,例如

if (!(scalep = malloc (sizeof *scalep))) { /* allocate/validate */ 
     fprintf (stderr, "error: virtual memory exhausted, scalep.\n"); 
     return 1; 
    } 

    if (scanf ("%3s", scalep->note) != 1) { /* validate ALL input */ 
     fprintf (stderr, "error: invalid input, scalep->note\n"); 
     return 1; 
    } 

最後,不需要prevp。這隻在刪除或交換節點時需要(在刪除或交換節點後,您必須重新指定prev指針指向next(您的linkp)),您在代碼中都不執行任何操作,也不需要int值你迭代current node = next node;來遍歷你的列表(有幾個變化如何做到這一點)。把所有的拼在一起,並試圖走出打好代碼在一個稍微更合乎邏輯的方式,你可以做類似下面的東西:

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

#define MAXC 4 

typedef struct scale_node_s { 
    char note[MAXC]; 
    struct scale_node_s *linkp; 
} scale_node_t; 

int main (void) 
{ 
    scale_node_t *scalep, *newp, *walker; 
    char tmp[MAXC] = ""; 

    if (!(scalep = malloc (sizeof *scalep))) { /* allocate/validate */ 
     fprintf (stderr, "error: virtual memory exhausted, scalep.\n"); 
     return 1; 
    } 

    if (scanf ("%3s", scalep->note) != 1) { /* validate ALL input */ 
     fprintf (stderr, "error: invalid input, scalep->note\n"); 
     return 1; 
    } 

    scalep->linkp = NULL; 

    while (scanf ("%3s", tmp) == 1) { 

     if (!(newp = malloc (sizeof *newp))) { /* allocate/validate */ 
      fprintf (stderr, "error: virtual memory exhausted, newp.\n"); 
      break; 
     } 
     strcpy (newp->note, tmp); /* set note and linkp */ 
     newp->linkp = NULL; 

     walker = scalep;   /* set walker to scalep */ 
     while (walker->linkp)  /* find last node */ 
      walker = walker->linkp; /* linkp !NULL move to next node */ 

     walker->linkp = newp; 
    } 

    walker = scalep; /* output list */ 
    while (walker) { 
     printf ("%s\n", walker->note); 
     walker = walker->linkp; 
    } 

    walker = scalep; /* free list memory */ 
    while (walker) { 
     scale_node_t *victim = walker; /* save victim address */ 
     walker = walker->linkp; 
     free (victim);     /* free victim */ 
    } 

    return 0; 
} 

示例使用/輸出

$ echo "a b c d e" | ./bin/llhelp 
a 
b 
c 
d 
e 

內存使用/錯誤檢查

在您編寫的動態分配內存的代碼中,您有2 的責任(1)總是保留一個指向內存塊的起始地址的指針,所以,(2)當它不再需要時,它可以被釋放爲

這是你必須使用一個內存錯誤檢查程序,以確保你不要試圖超越寫/你分配的內存塊的邊界之外,嘗試讀取或底座上未初始化值條件跳轉,最後,確認你釋放了你分配的所有內存。

對於Linux valgrind是正常的選擇。每個平臺都有類似的內存檢查器。它們都很簡單,只需通過它運行你的程序。

$ echo "a b c d e" | valgrind ./bin/llhelp 
==25758== Memcheck, a memory error detector 
==25758== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==25758== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 
==25758== Command: ./bin/llhelp 
==25758== 
a 
b 
c 
d 
e 
==25758== 
==25758== HEAP SUMMARY: 
==25758==  in use at exit: 0 bytes in 0 blocks 
==25758== total heap usage: 5 allocs, 5 frees, 80 bytes allocated 
==25758== 
==25758== All heap blocks were freed -- no leaks are possible 
==25758== 
==25758== For counts of detected and suppressed errors, rerun with: -v 
==25758== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

總是確認您已釋放所有分配的內存,並且沒有內存錯誤。

如果您有任何其他問題,請仔細查看並告訴我們。

相關問題