2015-08-24 2 views
-5
#include<stdio.h> 
int main() 
{ 

    char *str; 

    gets(str); 

    puts(str); 

return 0; 
} 

выход = Сегментация FaultКак указатели выделить память

Почему он дает ошибку сегментации?

+7

Указатели не выделяют память. – juanchopanza

+1

Если вы хотите выделить память, вам нужно вызвать 'malloc()' – Barmar

+0

'str' - это просто указатель. В какой области памяти указывается 'str'? Не знаете? Я тоже, потому что вы его не инициализировали. Он мог указывать куда угодно. На самом деле вам повезло, что он разбился. – cdarke

ответ

2

В случае

gets(str); 

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

Использование (попытки записать или даже читать с) Непознанная память вызывает undefined behavior. Ошибка сегментации является одним из побочных эффектов.

Тем не менее, gets() является чистое зло, из-за возможных проблем переполнения буфера. Вместо этого используйте fgets().

7

Ответ на вопрос «как указатели выделяют память» очень прост: они этого не делают. Вот почему вы получаете ошибку сегментации: доступ к данным из неинициализированного указателя равен неопределенное поведение.

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

char *str = malloc(10); 
fgets(str, 10, stdin); 
puts(str); 

Важная вещь, чтобы отметить о приведенном выше затруднительного является то, что fgets используется вместо устаревшей gets. Это связано с тем, что fgets позволяет рассказать функции, сколько памяти она может использовать в вашем буфере, а gets предполагает, что у нее есть вся необходимая память, что приводит к переполнению буфера.

+0

спасибо, сэр! ваше предложение очень помогло ...... –

+1

@ShubhamTiwari Добро пожаловать. Если это ответит на ваш вопрос, подумайте о принятии ответа, нажав на серый флажок рядом с ним. Это позволит другим посетителям сайта узнать, что ваша проблема решена, и заработайте значок на переполнении стека. – dasblinkenlight

1

Необходимо перенести первую страницу. Как это:

#include <stdio.h> 

int main() 
{ 

    char *str; 

    str = malloc(4096); 
    gets(str); 

    puts(str); 

    free(str); 
    return (0); 
} 

Это позволит писать на ул.

Для лучшего распределения памяти может быть хорошей идеей узнать, сколько памяти вам нужно, а не произвольное «4096».

Кроме того, не забудьте использовать бесплатный(), когда он вам больше не нужен.

2

Когда вы объявляете указатель, все, что вы сделали, зарезервировано для хранения адреса другого объекта; вы не выделили места для этого другого объекта.

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

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
str   0xfff86400  ?? ?? ?? ?? // ?? represents unknown byte value 

переменнаяstr находится по адресу 0xfff86400.Так как вы объявили str с auto продолжительности хранения (то есть, в пределах функции) и не явно инициализировать его, его значение неопределенными; он содержит неизвестный бит-шаблон, который (скорее всего) не соответствует записываемому адресу в вашей программе. gets пытается записать данные недействительный адрес, следовательно segfault . Ни один из входных процедур (fgets, scanf, fscanf, fread и т.д.) не будет выделять память для хранения фактического ввода; это ваша ответственность.

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

char buf[8] = "blah!"; 
char *str = buf; 

Это выделяет буфер для хранения до 8 символов, а затем присваивает адрес первого элемента этого буфера str, что дает нам что-то вроде этого:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
buffer  0xfff86400  'b' 'l' 'a' 'h' 
      0xfff86404  '!' 00 ?? ?? 
str   0xfff86408  ff f8 64 00 

Кроме того, вы можете использовать mallocдля динамического выделения памяти для str, чтобы указать:

char *str = malloc(BUF_SIZE); 

malloc резервирует BUF_SIZE байт для хранения строки ввода и присваивает указатель на это пространство для str.


1. Строго говоря, поведение на разыменования неверный указатель является неопределенным; segfault является одним из многих возможных результатов. Это может так же легко сбить что-то важное, что ваша программа продолжает работать, но теперь с правами администратора.