LINUX.ORG.RU

почему и при каких условиях scanf(«%i») будет крашится?

 ,


0

1

есть авторитетное мнение что если следующей проге на стдин всунуть файлик размером чуть больше 2Мб то она закрешится. у меня все работает отсюдова вопрос.

#include <stdio.h>
int main()
{
    int a;
    scanf("%i", &a);
    return 0;
}
★★★★★

есть авторитетное мнение что если следующей проге на стдин всунуть файлик размером чуть больше 2Мб то она закрешится

стек кончится — будет крешится

у меня все работает

не кончился.

emulek
()
Ответ на: комментарий от emulek

С чего бы ему кончаться? Сканф же не перегоняет данные под указатель, а парсит вход и результат заносит под указатель.

staseg ★★★★★
()

Почему-то ещё никто не упомянул какой это scanf и что за файлик

будет крашится

Нет слов. Мариванна говорит: «Будет крошиться». Впрочем, знакомые с компьютерным сленгом граммарнаци тоже останутся недовольными.

avc_fan
()
Ответ на: комментарий от staseg

С чего бы ему кончаться? Сканф же не перегоняет данные под указатель, а парсит вход и результат заносит под указатель.

угу. Надо смотреть реализацию scanf(3).

emulek
()
Ответ на: комментарий от staseg

Нельзя ли предположить, что некоторый сферический в вакууме scanf использует stack-allocated буфер для разбора входа?

avc_fan
()

Да в общем-то нечему здесь валиться, считает один инт и все.

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

int
main(int argc, char *argv[])
{
    int i = 0;
    char s[100];

    scanf("%i", &i);
    printf("i: %d\n", i);

    fgets(s, sizeof(s), stdin);
    printf("s: %s\n", s);

    return 0;
}
12345qwe
i: 12345
s: qwe
12345678901234567890qwe
i: -1
s: qwe
./x < data (~16Mb of '1')
i: -1
s: 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
anonymous
()
Ответ на: комментарий от avc_fan

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

staseg ★★★★★
()
Последнее исправление: staseg (всего исправлений: 1)

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

anonymous
()

есть неавторитетное мнение, что это зависит от конкретной реализации и окружения

wota ★★
()
Ответ на: комментарий от cvv

это мнение одной довольно неплохой системы статического анализа кода.

вы уверены, что она имела в виду именно модификатор «%i»?? скорее статический анализатор ругнулся на scanf вообще (исторически не считается безопасной функцией) или передачу адреса из стека на запись (хотя это паранойя)

MKuznetsov ★★★★★
()
Ответ на: комментарий от cvv

А можно весь выхлоп этой системы в студию? И пример, на который она ругается. Вполне возможно, что проблема вообще не в сканфе.

Gvidon ★★★★
()

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

При каких условиях: есть _потенциальная_ возможность падения на некоторых реализациях libc (ЕМНИП, старый, очень старый glibc подвержен этой напасти) - то есть всё полностью зависит от реализации libc. А ещё ЕМНИП scanf(«%i», &a); - это UB. Элементарно обходится записью scanf(«%10i», &a); но лучше использовать strtol.

Прислушаться к авторитетному мнению возможно и стоит, мало ли какой кривой «альтернативный» libc попадётся, особенно на оффтопик-ОСях.

RPG
()

buffer overrun detected.

%i - Integer - Any number of digits, optionally preceded by a sign (+ or -). и бла бла бла

То а сколько там digits в один инт влезет? sizeof(int) ?

Хотя про %d тоже самое написанно. Так что оно в итоге читать будет, и что сделает если «Any number of digits» не вмещаются в инт?

А крэшится будет в зависимости от погоды на марсе, и от содержимого памяти конечно же, если там всё таки есть overrun.

batbko
()
Последнее исправление: batbko (всего исправлений: 1)

scanf("%i", &a);

Ужас-то какой! Это же жопа! Читаешь в буфер от пробела до пробела, а потом вызываешь strtol для целых или strtoll для длинных с контролем.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

смотри вот тебе ужас рядом:

sprintf(buf, "%s%d", buf, x);

а то -так - просто легаси код имени какогото кетайца

cvv ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Тут тебя конечно пацаны спасают, но всё же. Ну же, и как же я использую мемкопи?

Ну давай, почему тут надо юзать memmove: memcpy((ptr - 10), ptr, 100500); ? Поясни мне попацаночке.

anonymous
()
Ответ на: комментарий от beastie

Ити, мой миленький зайчик. Давай я тебе объясняю в чем проблема, лапулечка.

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

Вот возмём процессор, основной юзкейс при обходе памяти - это повозрастанию. Дак вот, лапуля, дяди, которые пилят этот процессор - это понимают. И основной юзкейс должен быть эффективен минимум так же, либо даже в ущерб не осовным юзкейсам.

В х86 обход памяти в обе сторы равнозначный - это особенность архитектуры, лапуля. Ну не могут пацаны делать по другому, нельзя делать процессор, который будет тормазить на основном юзкейсе.

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

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

highly optimized for current processors.

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

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

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

anonymous
()
Ответ на: комментарий от beastie

Давай, лапуличка, я тебе ещё расскажу о том, как надо писать тесты, тыж тогда меня забанил.

И в чем проблема твоей мемкопи.

http://pastebin.com/gZ4bmAFu

Видишь, лапуля - мы тут приминили скилл вставки мемкопи куда надо, ещё капильки скилла - и вуаля, мы сократили оверхед в 9раз.

Далее, лапуля, мы знаем, что наша мемкопи кусок какахи. Т.е. когда надо копировать там память - копировать её можно как угодно, разницы нету. Когда же мы копируем кеш - разница есть. Кеш копируется полным анроллом и максимальной длинны регистрами.

Плюс мы копируем всегда 128байт, ибо любая строка меньше 128байт.

Если мы это сделаем: http://pastebin.com/NPZQyDcM

Мы уменьшим оверхед с 10-14мс до 0.89, из которых 0.67 - оверхед на сам вызов функции и прочее. Т.е. мы уменьшили оверхед с 9,33-13,33 до 0.22 т.е. 11,33/0.22 - 51,5раз.

И всё это благодаря скиллу мемкопи, лапуля. А всякие пацаны будут говорить, что «код говно» и прочее, но мы-то с тобою знаем, зая, почему они так говорит.

Пердак горит - нам всё понятно, не будь, зая, таким. Будь человеком.

anonymous
()
Ответ на: комментарий от anonymous

Плюс мы копируем всегда 128байт, ибо любая строка меньше 128байт.

you make my day.

emulek
()
Ответ на: комментарий от anonymous

слушай, а твой сенсей что-нить сам пишет, или это твоя тулпа?

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.