Вопрос по c – Ошибка сегментации - C [дубликат]

10

This question already has an answer here:

Crash or “segmentation fault” when data is copied/scanned/read to an uninitialized pointer 4 answers

Почему следующий код возвращается с ошибкой сегментации? Когда я закомментирую строку 7, ошибка сегмента исчезнет.

int main(void){
      char *s;
      int ln;
      puts("Enter String");
      // scanf("%s", s);
      gets(s);
      ln = strlen(s); // remove this line to end seg fault
      char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome
      dyn_s = s;
      dyn_s[strlen(s)] = '\0';
      puts(dyn_s);
      return 0;
    }

Ура!

@Lundin, пожалуйста, укажите, что это дубликат? Если вы имеете в видуstackoverflow.com/questions/37549594/…Я утверждаю, что мой вопрос на 4 года старше ceod

Ваш Ответ

5   ответов
1

#include <stdio.h>
int
main(void)
{
  char *line = NULL;
  size_t count;
  char *dup_line;

  getline(&line,&count, stdin);
  dup_line=strdup(line);

  puts(dup_line);

  free(dup_line);
  free(line);

  return 0;
}
Здорово! Спасибо KAction! Был немного занят в последнее время. Я обещаю, что в ближайшее время я более подробно расскажу о внутренних махинациях вашего кода. Хороших выходных. Ура! ceod
Привет! Я никогда не использовал функции getline () и strdup (). Я тоже не думаю, что видел их раньше. Спасибо за представление их мне;). К сожалению, ваш код работает с ошибкой сегмента! ceod
line должно быть инициализировано с NULL. Да, С может быть жестоким.
Странный. Предупреждение о неявной декларации, правильная работа для меня. Система GNU / Linux, gcc 4.6.3.
3

int main(void){
      char *s;
      int ln;
      puts("Enter String");
      // scanf("%s", s);
      gets(s);
      ln = strlen(s); // remove this line to end seg fault
      char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome
      dyn_s = s;
      dyn_s[strlen(s)] = '\0';
      puts(dyn_s);
      return 0;
    }

Лучше:

#include <stdio.h>
#define BUF_SIZE 80

int 
main(int argc, char *argv[])
{
      char s[BUF_SIZE];
      int ln;
      puts("Enter String");
      // scanf("%s", s);
      gets(s);
      ln = strlen(s); // remove this line to end seg fault
      char *dyn_s = (char*) malloc (strlen(s)+1); //strlen(s) is used here as well but doesn't change outcome
      dyn_s = s;
      dyn_s[strlen(s)] = '\0';
      puts(dyn_s);
      return 0;
    }

Лучший:

#include <stdio.h>
#define BUF_SIZE 80

int 
main(int argc, char *argv[])
{
      char s[BUF_SIZE];
      int ln;
      puts("Enter String");
      fgets(s, BUF_SIZE, stdin); // Use fgets (our "cin"): NEVER "gets()"

      int ln = strlen(s); 
      char *dyn_s = (char*) malloc (ln+1);
      strcpy (dyn_s, s);
      puts(dyn_s);
      return 0;
    }
@TheMask: Спасибо !!! ceod
@resonant_fractal: проверить:cplusplus.com/reference/clibrary/cstdio
И вообщеcast malloc() удаление результата, проверьте, если вы не получилиNULL значение.char *dyn_s = malloc(ln + 1); if(!dyn_s) { printf("No mem!\n"); exit(EXIT_FAILURE);} или вы можете получить другую ошибку сегментации.
Еще лучше:char *dyn_s = malloc(ln + 1);, И обратите внимание, чтоfgets() оставляет окончание'\n' в буфере;gets() отбрасывает это (ноgets() все еще катастрофически плохо).
Здорово! Благодарю. Какие замечательные ресурсы у вас есть, ссылки на поведение часто используемых функций ввода-вывода? ceod
1
char *s  does not have some memory allocated . You need to allocate it manually in your case . You can do it as follows
s = (char *)malloc(100) ;

так как вы больше не будете ссылаться на неизвестное местоположение.

16

s неинициализированный указатель; Вы пишете в случайное место в памяти. Это вызоветundefined behaviour.

Вам нужно выделить немного памяти дляs, Также,никогда не использоватьgets; нет способа предотвратить его переполнение выделенной памяти. использованиеfgets вместо.

Большое спасибо, Оли! ceod
@ TheMask Спасибо! Но как насчет malloc в строке 8, использующей то же выражение strlen? Вся программа запускается без ошибок, если я просто удаляю строку 7. Или вы, ребята, получаете что-то другое? ceod
@resonant_fractal: Сложно сказать. Неопределенное поведение по определению означает, что ваша программа может делать все что угодно, в том числе и непредсказуемым образом. Я мог бы догадаться, но единственный способ узнать наверняка - посмотреть на машинный код, созданный вашим компилятором.
Большое спасибо, Оли! Прошу прощения за то, что я вредитель, но я должен понять, что добавление упомянутой мной строки приводит к тому, что неопределенное поведение приводит к ошибке сегмента. Не могли бы вы помочь мне визуализировать причинно-следственную связь? ceod
посколькуstrlen() Функция пытается получить доступ к пространству, которое не существует. такой же какstrlen(NULL), Внутри функции есть что-то вроде:size_t strlen(char *s) { char *p=s; while( *p++ ) & Lt; это вызывает ошибку сегментации.
1

scanf("%s", s); закомментировано. Это означает, что s неинициализирован, поэтому, когда эта строкаln = strlen(s); выполняется, вы получаете ошибку сегмента.

Это всегда помогает инициализировать указатель на NULL, а затем проверять на нулевое значение перед использованием указателя.

Error: User Rate Limit Exceeded ceod
Error: User Rate Limit ExceededwrongError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы