Ошибка сегментации (ядро сброшено) в программе в c? - PullRequest
1 голос
/ 12 апреля 2020

Я студент и изучаю c (программирование в ANSI c -> пятое издание) и сталкиваюсь с ошибкой ниже:

Я реализую одну программу с typedef

В приведенной ниже c программе выдается ошибка:

main.c:8:6: warning: ‘gets’ is deprecated [-Wdeprecated-declarations]                                                                                                      
/usr/include/stdio.h:638:14: note: declared here                                                                                                                           
main.c:(.text+0x1f): warning: the `gets' function is dangerous and should not be used.                                                                                     
enter name:cara                                                                                                                                                            
Segmentation fault (core dumped) 

Программа:

#include <stdio.h>

char * read(void);   //here I m writing prototype but I don't know what is the prototype and why here write the prototype?
char * read(void)
{
     char * name;
     printf("enter name:");
     gets(name);  //get string input using gets(..) function
     return name;
}

void main()
{
   char * name;
   name = read();
   printf("welcome,%s\n",name);
}

Программа выше - сложность, поэтому я использую typedef в следующей программе:

эта программа работает постоянно, почему ?

#include <stdio.h>

typedef char * string;

string read(void);   
string read(void)
{
     string name;
     printf("enter name:");
     gets(name); 
     return name;
}

void main()
{
   string name;
   name = read();
   printf("welcome,%s\n",name);
}

Что я делаю не так?

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Есть несколько вещей не так с этим. Когда вы делаете char * name, вы определяете name как указатель на символ, но вы фактически не выделяете места для строки, которая будет сохранена. Следовательно, когда вы пытаетесь записать значения в эту строку, вы записываете значения в случайном месте, которое может быть недоступно для записи или может содержать важные данные, которые нельзя перезаписать. Вместо этого попробуйте объявить имя как char name[256];, чтобы выделить для него достаточно места. Кроме того, не используйте gets, так как это может привести к очень, очень неприятным вещам. Вместо этого используйте fgets для чтения ввода и укажите верхний предел количества символов, равный объему данных, которые вы выделили. Итак, если вы объявили имя как char name[256];, вызовите fgets с fgets(name, 256, stdin);

0 голосов
/ 12 апреля 2020

Программа имеет неопределенное поведение, потому что вы используете неинициализированный указатель с неопределенным значением

 char * name;
 printf("enter name:");
 gets(name);

Вам необходимо выделить память, в которой вы собираетесь читать строку.

Как для функции gets тогда это действительно небезопасная функция и больше не поддерживается стандартом C. Вместо этого используйте стандартную C функцию fgets.

Обратите внимание, что согласно стандарту C функция main без параметров должна быть объявлена ​​как

int main( void )

И используя typedef как это

typedef char * string;

- плохая идея. Например, используя это имя typedef, вы не можете объявить указатель на постоянные данные, такие как

const char *p;

, потому что это объявление

const string p;

не эквивалентно приведенному выше объявлению, а означает следующее объявление

char * const p;

Программа может выглядеть, например, следующим образом

#include <stdio.h>

char * read( char *s, size_t n )
{
    s[0] = '\0';

    printf( "Enter name: " );
    fgets( s, n, stdin );

    return s;
}

int main( void )
{
    enum { N = 100 };

   char name[N];

    printf( "%s", read( name, N ) );
}

Ее вывод может выглядеть следующим образом:

Enter name: rahul_
rahul_

Обратите внимание, что функция fgets можно добавить введенную строку с символом новой строки '\n'. Чтобы удалить его, вы можете использовать следующий трюк

#include <string.h>

//...

name[ strcspn( name, "\n" ) ] = '\0';
...