Сбой или "ошибка сегментации" при копировании/сканировании/чтении данных в неинициализированный указатель

этот вопрос предназначен для использования в качестве ссылки для всех Часто задаваемые вопросы о сущности:

почему я получаю таинственный сбой или "ошибка сегментации", когда я копирую/сканирую данные по адресу, на который указывает неинициализированный указатель?

например:

char* ptr;
strcpy(ptr, "hello world"); // crash here!

или

char* ptr;
scanf("%s", ptr); // crash here!

3 ответов


указатель - это специальный тип переменной, который может содержать только адрес другой переменной. Он не может содержать никаких данных. Вы не можете "копировать / хранить данные в указатель" - это не имеет никакого смысла. Вы можете установить указатель только на данные, выделенные в другом месте.

это означает, что для того, чтобы указатель был значимым, он всегда должен указывать на допустимое местоположение памяти. Например, он может указывать на память, выделенную в стеке:

{
  int data = 0;
  int* ptr = &data;
  ...
}

или памяти динамически выделяется в куче:

int* ptr = malloc(sizeof(int));

это всегда ошибка, чтобы использовать указатель, прежде чем он был инициализирован. Он еще не указывает на действительную память.

эти примеры могут привести к сбоям программы или другим видам неожиданного поведения, таким как "ошибки сегментации":

/*** examples of incorrect use of pointers ***/

// 1.
int* bad;
*bad = 42;

// 2.
char* bad;
strcpy(bad, "hello");

вместо этого вы должны убедиться, что указатель указывает на (достаточно) выделенную память:

/*** examples of correct use of pointers ***/

// 1.
int var;
int* good = &var;
*good = 42;

// 2.
char* good = malloc(5+1); // allocates memory for 5 characters and 1 terminator
strcpy(good, "hello");

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

int* p1 = NULL; // pointer to nowhere
int* p2;        // uninitialized pointer, pointer to "anywhere", cannot be used yet

тем не менее, если вы попытаетесь получить доступ к памяти, на которую указывает нулевой указатель, вы можете получить аналогичные проблемы, как при использовании неинициализированного указателя: сбои или ошибки сегментации. В лучшем случае, заметит, что вы пытаются получить доступ к адресу null, а затем выдает "исключение нулевого указателя".

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


читайте далее:

указатели, указывающие на недопустимые данные
как получить доступ к локальной переменной из другой функции с помощью указателей?
может ли локальная переменная доступ к памяти за ее пределами?

ошибка сегментации и причины
что такое ошибка сегментации?
почему я получаю ошибку сегментации при записи в строку, инициализированную "char *s", но не " char s []"?
в чем разница между char s[] и char *s?
окончательный список общих причин ошибок сегментации
что такое автобус ошибка?


  1. указатели указывают только на местоположение памяти. Вы создали указатель, но еще не привязались к местоположению памяти. strcpy хочет, чтобы вы прошли два указателя (сначала нельзя быть постоянным), которые указывают на два массива символов, таких как эта подпись:

    char * strcpy ( char * destination, const char * source );
    

    пример использования:

    char* ptr = malloc(32);  
    strcpy(ptr, "hello world");
    
    char str[32];  
    strcpy(str, "hello world");
    
  2. вы можете попробовать следующий фрагмент кода для чтения строки до достижения символа новой строки (*вы также можете добавить другие символы пробелов, такие как "%[^\t\n]s"(tab, newline) или "%[^ \t\n]s" (пробел, табуляция, перевод строки)).

    char *ptr = malloc(32);
    scanf("%31[^\n]", ptr);
    

    (в реальной жизни, не забудьте проверить возвращаемое значение из scanf()!)


это происходит потому, что у вас есть не выделено память указатель char* ptr . В этом случае вы должны динамически выделять память для указателя.

две функции malloc() и calloc() может использоваться для dynamic memory allocation.

попробуйте этот код :-

  char* ptr;
  ptr = (char *) malloc(sizeof(char)*50); // allocate space for 50 characters.
  strcpy(ptr, "hello world");

при использовании *ptr над Не забудьте освободить выделено *ptr .Это можно сделать с помощью free() функция.

  free(ptr);  // deallocating memory.

размер динамически выделяемая память можно изменить с помощью realloc().

  ptr = (char *)realloc(ptr, sizeof(char)*100);// allocate space for 0 characters.

в большинстве случаев "ошибка сегментирования" происходит из-за ошибки в выделение памяти или массив из bound случаях.