2013-06-24 2 views
-1

У меня есть простая функция ввода, которая работает:сбоев, когда я поставил простого ИНТ переменной

int main(void) 
{ 
    char *first; 
    char *last; 

    scanf("%s", first); 

    printf("%s", last); 

    return 1; 
} 

Но когда я начинаю расширять свою работу, и поставить простой счетчик, программа аварию:

int main(void) 
{ 
    int i = 0; 
    char *first; 
    char *last; 

    scanf("%s", first); 

    printf("%s", last); 

    return 1; 
} 

любой идея?

+3

Вы не должны выделять свой символ * перед тем, как попытаться получить к ним доступ? –

+2

Ваш простой функция делает ** нет ** работа. – meagar

+1

Вы должны * присваивать * переменную значение, прежде чем * использовать * его значение. Вы не делаете этого для 'first' или' last'. –

ответ

2
char *first; 

scanf("%s", first); 

first не инициализируются перед вызовом scanf: его значение перед вызовом является неверный адрес.

+0

также может быть полезно использовать конструкцию типа 'while (scanf («% s », first)! = 0) {...}', чтобы проверить, была ли введенная строка символов – Zaiborg

+0

+1 для отличной, сжатой ответ - но это не объясняет, почему добавление 'int i = 0;' имеет значение. – abarnert

+0

@abarnert Программа вызывает неопределенное поведение, а undefined не определено. – ouah

1

Вы должны либо динамически выделить свой char* перед использованием scanf(), чтобы сохранить в нем или, возможно, переключиться на массив символов.

0

Ваша first переменная не инициализируется. Либо объявляйте его как массив, либо выделяйте динамически исходя из ваших потребностей.

  1. массив версия,

    int main(void) 
    { 
        char first[ SIZE ];  // define SIZE as per your need 
        char last[ SIZE ]; 
    
        scanf("%s", first); 
        printf("%s", last);  // FIXME : last is again not initialized 
        return 1; 
    } 
    
  2. Динамическая версия,

    int main(void) 
    { 
        char *first = malloc(SIZE);  // define SIZE as per your need 
        char *last = malloc(SIZE); 
    
        scanf("%s", first); 
        printf("%s", last);  // FIXME : last is again not initialized 
    
        free(first); first = NULL; 
        free(last); last = NULL; 
    
        return 1; 
    } 
    
1

Проблема заключается в том, что first является неинициализированным переменная указатель, то есть указатель имеет произвольную значение- он может указывать в любом месте в памяти.

Если вам очень повезло, оно заканчивается тем, что указывает на неиспользуемую выделенную память, поэтому чтение строки в нее происходит.

Если вам повезет, это указывает на невозвращенный адрес, поэтому чтение строки в нее вызывает segfault.

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


Добавление int i = 0; не меняет ничего, кроме «повторного кидать кости». Вы также можете получить разные результаты, например, изменив флаги компилятора (особенно если включить или отключить функции отладки или оптимизации).


Например, может быть область стек получает выделяется из выглядит следующим образом, когда ваша main функция вводится:

pointer to return address in the middle of libc 
pointer to data segment 
0 

В первой версии вашего кода, вы ничего не инициализировать, и first заканчивается наследованием значения указателя на сегмент данных, поэтому сканирование в него работает. Во второй версии i заканчивается наследованием указателя на сегмент данных (и переписывает его 0), а first заканчивает наследование значением 0, поэтому сканирование в него segfaults.


Если вы заинтересованы в том, что происходит на самом деле, вы можете посмотреть на сборку, порожденного -S флагом (или эквивалент для компилятора), или вы можете просто printf("%p\n", first), а затем посмотреть, что адрес, который вы получите и выяснить, что там отображается.

Но на самом деле, неважно почему не работает. Он не должен работать, и единственным решением является правильная инициализация указателя на что-то действительное (как объясняет ответ ouah, а остальные объясняют).