2017-05-07 18 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) 

总是确认您已释放所有分配的内存,并且没有内存错误。

如果您有任何其他问题,请仔细查看并告诉我们。

相关问题