Сбой или "ошибка сегментации" при копировании/сканировании/чтении данных в неинициализированный указатель
этот вопрос предназначен для использования в качестве ссылки для всех Часто задаваемые вопросы о сущности:
почему я получаю таинственный сбой или "ошибка сегментации", когда я копирую/сканирую данные по адресу, на который указывает неинициализированный указатель?
например:
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?
окончательный список общих причин ошибок сегментации
что такое автобус ошибка?
-
указатели указывают только на местоположение памяти. Вы создали указатель, но еще не привязались к местоположению памяти.
strcpy
хочет, чтобы вы прошли два указателя (сначала нельзя быть постоянным), которые указывают на два массива символов, таких как эта подпись:char * strcpy ( char * destination, const char * source );
пример использования:
char* ptr = malloc(32); strcpy(ptr, "hello world");
char str[32]; strcpy(str, "hello world");
-
вы можете попробовать следующий фрагмент кода для чтения строки до достижения символа новой строки (*вы также можете добавить другие символы пробелов, такие как
"%[^\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 случаях.