【问题标题】:C Function returning pointers - memory fault, core dumpedC函数返回指针-内存故障,核心转储
【发布时间】:2014-12-27 19:57:26
【问题描述】:

请,有人能告诉我为什么下面的程序可以编译,但是当我尝试运行它时,我收到了内存错误的错误消息? 该程序甚至没有执行 main 函数的第一行。我把 printf 行放在 main 函数的开头,但它没有被执行。

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


 typedef struct element {
   struct element *next;
   struct element *previous;
   char imie[256];
   char nazwisko[256];
   char tytul[256];
   int numer;
   double cena;     
 } el_listy;


el_listy* tworzpierwszy(el_listy *nowy){
   nowy=(el_listy*)realloc(nowy, sizeof(el_listy));
   strcpy(nowy->imie,"");
   strcpy(nowy->nazwisko,"");
   strcpy(nowy->tytul,"");
   nowy->numer=0;
   nowy->cena=0.00;
   nowy->next=NULL;
   nowy->previous=NULL;
   return nowy;
}


 void addoddolu (el_listy *lista){
   el_listy *wsk, *nowy;
   wsk = lista;
   while (wsk->next != NULL)
     { 
     wsk = wsk->next; /* przesuwamy wsk aż znajdziemy ostatni element */
     }
   nowy =(el_listy*) malloc (sizeof(el_listy));
   char bufor[256];
   int nm;
   double no;
   printf("Podaj imie autora ksiazki > ");
   if(scanf("%s", bufor)==1){strcpy(nowy->imie,bufor);};
   printf("Podaj nazwisko autora ksiazki > ");
   if(scanf("%s", bufor)==1){strcpy(nowy->nazwisko, bufor);};
   printf("Podaj tytul ksiazki > ");
   if(scanf("%s", bufor)==1){strcpy(nowy->tytul, bufor);};
   printf("Podaj numer katalogowy ksiazki");
   if(scanf("%d", &nm)==1){nowy->numer=nm;};
   printf("Podaj cene ksiazki > ");
   if(scanf("%lf", &no)==1){nowy->cena=no;};
   nowy->next = NULL;
   nowy->previous=wsk;
   wsk->next = nowy; /* podczepiamy nowy element do ostatniego z listy */
 }

void addodgory (el_listy *lista){
   el_listy *wsk, *nowy;
   char bufor[256];
   int nm;
   double no;
   wsk = lista;
   nowy =(el_listy*) malloc (sizeof(el_listy));
   printf("Podaj imie autora ksiazki > ");
   if(scanf("%s", bufor)==1){strcpy(nowy->imie,bufor);};
   printf("Podaj nazwisko autora ksiazki > ");
   if(scanf("%s", bufor)==1){strcpy(nowy->nazwisko, bufor);};
   printf("Podaj tytul ksiazki > ");
   if(scanf("%s", bufor)==1){strcpy(nowy->tytul, bufor);};
   printf("Podaj numer katalogowy ksiazki");
   if(scanf("%d", &nm)==1){nowy->numer=nm;};
   printf("Podaj cene ksiazki > ");
   if(scanf("%lf", &no)==1){nowy->cena=no;};
   nowy->previous = NULL;
   nowy->next=wsk;
   wsk->previous = nowy; /* podczepiamy nowy element do ostatniego z listy */
 }

 void wypiszliste(el_listy *lista){
   el_listy *wsk=lista;
   int numer=1;
   while( wsk != NULL )
     {
     printf ("Ksiazka %d, %s, %s, %s, %d, %lf \n", numer, wsk->imie, wsk->nazwisko, wsk->tytul, wsk->numer, wsk->cena);
     numer=numer+1;
     wsk = wsk->next;
     }
 }

void usunzlisty(el_listy *lista, int numer){
   el_listy *wsk=lista;
   while (wsk->next != NULL)
     {
     if (wsk->next->numer == numer) /* musimy mieć wskaźnik do elementu poprzedzającego */
       {
       el_listy *usuwany=wsk->next; /* zapamiętujemy usuwany element */
       wsk->next = usuwany->next;   /* przestawiamy wskaźnik next by omijał usuwany element */
       usuwany->next->previous=wsk;
       free(usuwany);               /* usuwamy z pamięci */
       } else
         {
         wsk = wsk->next;           /* idziemy dalej tylko wtedy kiedy nie usuwaliśmy */
         }                          /* bo nie chcemy zostawić duplikatów */
       }
 }

 int szukaj_nazwisko(el_listy *lista, char* nazwisko){
   el_listy *wsk;
   wsk = lista;
   while (wsk != NULL) {
     if (strcmp(wsk->nazwisko,nazwisko)==0) return wsk->numer;
        wsk = wsk->next;
     }
     return 0;
 }

 int main (){
   printf("Program glowny, pierwszy wiersz");
   el_listy *wskaznik;
   printf("Program glowny, drugi wiersz");
   el_listy* lista;
   lista = tworzpierwszy(wskaznik);
   addodgory(lista);
   wypiszliste(lista);
   return 0;
 }

【问题讨论】:

  • 不要转换mallocrealloc的结果:stackoverflow.com/questions/605845/…
  • 编译时包含所有警告和调试信息 (gcc -Wall -Wextra -g)。然后使用调试器 (gdb)
  • 始终检查 malloc 系列函数的返回值,以确保操作成功。
  • 标准输出被缓冲,只有当缓冲区满时才会发送到终端。要强制立即输出到终端,请使用 '\n' 结束 printf 格式字符串,或者(更好)在每个 printf 之后使用 'fflush(stdout);'
  • 关于这种行:if(scanf("%s", bufor)==1){strcpy(nowy->imie,bufor);};用户可以输入的字符数没有限制,因此很容易发生缓冲区溢出,这是未定义的行为,导致段错误事件。

标签: c


【解决方案1】:

您还没有在main() 中为wskaznik 调用malloc()。它应该类似于:

el_listy *wskaznik = (el_listy *) malloc(sizeof(struct element));

【讨论】:

  • 或者甚至只是el_listy *wskaznik = 0;,因为realloc() 很乐意使用空指针作为它的第一个参数。 (其实realloc()可以用来重新分配内存、释放内存、增加前一次分配的大小或减少前一次分配的大小——一体式内存分配系统!最好不要用于但是完全释放内存。不过,在第一次调用时使用空指针的自启动机制可能很有用。)
【解决方案2】:

在函数tworzpierwszy中更改这一行

nowy=(el_listy*)realloc(nowy, sizeof(el_listy));

进入

nowy=(el_listy*)malloc(sizeof(el_listy));

它会起作用的!

【讨论】:

  • 这是一个更好的解决方案,但是随着更改,tworzpierwszy() 的参数变得多余;进入函数时它的值是什么并不重要。所以,函数应该变成el_listy *tworzpierwszy(void) { el_listy *nowy = malloc(sizeof(*nowy)); …; return nowy; },并且调用也会改变。由于各种原因(包括年老),我并不强烈反对对 malloc() 的结果进行强制转换,但我总是通过编译选项来保护自己在使用或定义之前声明,我的编译将失败。
【解决方案3】:

tworzpierwszy 正在尝试重新分配一个从未分配过的指针,甚至从未以任何方式初始化过 (wskaznik)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-09
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多