2014-02-19 3 views
1

Пожалуйста, объясните мне следующий пример. Проблема проста, но результаты резкие.Объясните мне следующий выход программы C

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(int argc, char *argv[]) 
{ 
    int flag = 0; 
    char passwd[10]; 
    strcpy(passwd, argv[1]); 
    if(0 == strcmp("LinuxGeek", passwd)) 
    { 
     flag = 1; 
    } 

    if(flag) 
    { 
     printf("\n Password cracked \n"); 
    } 
    else 
    { 
     printf("\n Incorrect passwd \n"); 

    } 
    return 0; 
} 

Значение флага меняется на значение мусора после строки

strcpy(passwd, argv[1]); 

Однако, если определить переменную флаг, как,

int flag = 0 

после того, как линии

strcpy(passwd, argv[1]); 

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

+2

Вкратце: Неопределенное поведение. –

+0

Другие проблемы, чем это происходит, если длина argv [1]> 10 символов ... –

+0

Движение символов выполняется по-разному в разных реализациях. Таким образом, перекрывающиеся перемещения могут вызвать неожиданности. – Afaq

ответ

2

Когда я напечатал адрес flag и passwd Я получил 0x7fff3315c91c и 0x7fff3315c910 соответственно. Итак, я пришел к выводу, что значение passwd перезаписывает значение флага, если размер argv [1] больше 12 (в качестве разницы между адресами flag и passwd 12).

passwd адрес модели (0x7fff3315c910):| 10 | 11 | 12 | ........... | 1A | 1B |

flag адрес модели (0x7fff3315c91c):| 1C | ........

Из сказанного выше мы видим, что адрес flag является перезаписывается значением passwd

+0

Да, Сутирта, я согласен с тобой. Я сделал то же самое и понял, как память перезаписывается. Я использовал malloc() для passwd, и мой код работал. благодаря – Anand

1

Вы не производите проверку (длину, нулевой байт) на строках, которые вы манипулируете, особенно argv. Например, пароль ввода может не соответствовать вашей переменной passwd.

6

Короткий ответ заключается в том, что поведение вашей программы не определено, когда длина argv[1] больше девяти, потому что тогда вы переполняете буфер passwd.

Длинный ответ, что, по-видимому, ваш компилятор заказывает переменные в стеке в указанном порядке, так что перемещение flag после passwd ставит четыре дополнительных нулевых байтов после того, как буфер и strcmp признает один из них в качестве терминатора NUL на passwd.

Решение проблемы заключается, чтобы пропустить бесполезное копирование:

char *passwd = argv[1]; 

Или удалить переменную passwd в целом и сделать следующее сравнение:

strcmp("LinuxGeek", argv[1]) 
+1

Не забывайте, что нет проверки на то, что 'argc' больше 1. – Mario

Смежные вопросы