Форум программистов, компьютерный форум CyberForum.ru

scanf ? - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.74
Mikant
 Аватар для Mikant
1246 / 918 / 55
Регистрация: 08.12.2009
Сообщений: 1,294
02.04.2010, 23:41     scanf ? #1
господа, подскажите пожалуйста, почему после этого в VC++ вылетает исключение о нарушении доступа (access violation) к каким-то (по ходу одним из первых) адресам памяти???

C++
1
2
3
4
5
#include <stdio.h>
 
void main(){
    scanf("%lf");
}
даже вопрос разбивается на 2: почему вообще вылетает и почему вылетает ИМЕННО ПОСЛЕ завершения отработки main??? (даже если за этой строкой следует огромная программа)

естественно, если все по-честному делать: scanf("%lf", &buf); то никаких проблем нет.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.04.2010, 23:41     scanf ?
Посмотрите здесь:

C++ scanf в C
использование scanf C++
scanf. Разбиение. C++
C++ Затруднение со scanf
scanf for double C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
M128K145
Эксперт C++
 Аватар для M128K145
8272 / 3491 / 142
Регистрация: 03.07.2009
Сообщений: 10,707
03.04.2010, 00:02     scanf ? #2
потому что вы его неправильно используете.
Это вопрос аналогичен такому
почему код
C++
1
2
int a = 0;
++a;
работает, а
C++
1
2
int a;
++a;
бросает эксепшен
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
03.04.2010, 00:31     scanf ? #3
Mikant,
C
1
2
3
4
5
6
7
#include <stdio.h>
int main(void){
  double val;
  scanf("%lf", &val);
  printf("Value = %f\n", val);
  return 0;
}
Mikant
 Аватар для Mikant
1246 / 918 / 55
Регистрация: 08.12.2009
Сообщений: 1,294
03.04.2010, 00:50  [ТС]     scanf ? #4
M128K145, не, ну тут, понятное дело, непроинициализированная переменная... а у меня куда считанный дабл записывается? и когда?

easybudda, если дочитаете мой пост до конца - там это естественно есть

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

Добавлено через 3 минуты
M128K145, тем более ++a выбрасывает исключение в рантайме, а моя конструкция - нет... зараза...
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
03.04.2010, 05:06     scanf ? #5
Исключение выбивает потому что происходит попытка записи в секцию кода, которая по умолчанию имеет атрибут только чтение.
Mikant
 Аватар для Mikant
1246 / 918 / 55
Регистрация: 08.12.2009
Сообщений: 1,294
03.04.2010, 12:45  [ТС]     scanf ? #6
kazak, а почему запись в эту секцию происходит ПОСЛЕ main??
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
03.04.2010, 17:53     scanf ? #7
А почему ты решил, что это происходит после мэйна?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
03.04.2010, 18:53     scanf ? #8
Цитата Сообщение от Mikant Посмотреть сообщение
почему вообще вылетает
В scanf'е ты указал "%lf". Сие означает, что следующим параметром ожидается указатель на double. Но указатель ты не подал. Поэтому в том месте памяти, где среди параметров ожидался указатель, реально пришёл мусор (неинициализированное значение). Этот мусор далее начал трактоваться как указатель, по которому внутри scanf'а начала выполняться запись введённого значения. С вероятностью, близкой к единице, такой код сломается

Цитата Сообщение от Mikant Посмотреть сообщение
и почему вылетает ИМЕННО ПОСЛЕ завершения отработки main???
Присоединяюсь к вопросу, а почему ты решил, что после main'а? Но если это и вправду так, то тот мусор, который попал в scanf, оказался всё-таки валидным адресом в адресном пространстве процесса (в том смысле, что этот адрес виртуальной памяти отмапирован на физическую память). И по этому адресу, например, мог лежать адрес возврата из main'а или какая-нибудь другая системная информация, которую запортил scnaf
Mikant
 Аватар для Mikant
1246 / 918 / 55
Регистрация: 08.12.2009
Сообщений: 1,294
03.04.2010, 19:28  [ТС]     scanf ? #9
Цитата Сообщение от Evg Посмотреть сообщение
почему ты решил, что после main'а
ну, собсна, предыстория такова: у меня студентка курсовую пишет на плюсах (далеко не профиль, а я вообще .NETчик). пишет она прямо в университете, а там на древних компах только и установлен BC++3.1 (91 год, насколько я помню). писала она там, писала и проблем не было. курсовая примитивнейшая: считать из файла данные, пробежаться по ним парой фильтров и выгрузить. ну, естессна, в мэйне тупо подряд несколько вызовов простых функций. в универе - ни одной ошибки ни компилятор не выдает, ни в рантайме не вылетает. скоро им сдавать и позвал я ее к себе домой. дома - VS2008. стал портировать (постоянные предупреждения об использовании небезопасных функций и прочее), все сделал: ни одного предупреждения или ошибки не осталось. далее при запуске программа вела себя как положено, но после завершения (все успешно выгрузив) выдавала это исключение (Необработанное исключение в "0xc0590000" в "DSP.exe": 0xC0000005: Access violation.). при этом на стеке ntdll.dll... -> c0590000(); решил я ошибку отловить. нашел в первой функции (считывания как раз). и уже на форум выложил минималистичный вариант отлова этой ошибки.

зы. при этом открывался еще какой-то файл с кодом, где на его "пустой" строке это исключение и выходило... повтрорить не получается

ззы. если всю программу трассировать по шагам - тот же эффект, соответственно
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
03.04.2010, 20:39     scanf ? #10
Значит такой кривой scanf затёр в памяти что-то в системной части и после завершения main сломался завершающий код
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
04.04.2010, 08:33     scanf ? #11
Цитата Сообщение от Mikant
все сделал: ни одного предупреждения или ошибки не осталось.
сообщение об ошибке на gcc

Код
[guest@station ~]$ ed
a
#include <stdio.h>

void main(){
        scanf("%lf");
}
.
2t0
1t$-1
,p

#include <stdio.h>

void main(){
        scanf("%lf");

}
$-1c
    return 0;
.
/scan/
        scanf("%lf");
s/ \+/    /
,p

#include <stdio.h>

void main(){
    scanf("%lf");
    return 0;
}
/voi/
void main(){
s/void/int/
s/()/(void)/
,p

#include <stdio.h>

int main(void){
    scanf("%lf");
    return 0;
}
w t.c
73
!gcc t.c -o t
!
!gcc -Wall t.c -o t
t.c: In function ‘main’:
t.c:5: предупреждение: недостаточно аргументов для указанного формата
!
!./t
abcd
!
!rm t t.c
!
q
[guest@station ~]$

она и не должна выдавать, так как может и не быть аргументов

Код
[guest@station ~]$ ed
a

#include <stdio.h>

int main(void)
{

}
.
$i
    return 0;
.
,p

#include <stdio.h>

int main(void)
{

    return 0;
}
/{/
{


c
    scanf("abc");
    scanf("%d");
    printf("abc is entered" "\n");
.
,p

#include <stdio.h>

int main(void)
{
    scanf("abc");
    scanf("%d");
    printf("abc is entered" "\n");
    return 0;
}
/%d/
    scanf("%d");
m+1
,p

#include <stdio.h>

int main(void)
{
    scanf("abc");
    printf("abc is entered" "\n");
    scanf("%d");
    return 0;
}
w t.c
124
!gcc -Wall t.c -o t
t.c: In function ‘main’:
t.c:8: предупреждение: недостаточно аргументов для указанного формата
!
!./t
abcdefg
abc is entered
!
!rm t.c t
!
q
[guest@station ~]$
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
04.04.2010, 14:02     scanf ? #12
accept, с gcc сравнивать не совсем корректно, потому как gcc выдаёт warning не совсем честным способом: он банально "узнаёт" функцию. Старые версии gcc делали это тупо по имени, а в современных версиях в инклюдах у функций printf (и всей группы), scanf (и всей группы) есть некий атрибут (не помню точно как он называется). говорящий о том, что прототип функции соотвествует действию printf'а и scanf'а соответсвенно. И поэтому gcc лезет разбирать форматную строку и проверяет типы последующих аргументов. Хотя компилятор не обязан заниматься такой ерундой. Это всего лишь пользовательская фича, но никак не стандарт языка. Прочие компиляторы как правило этим не заморачиваются и предупреждений не выдают.

Ну и для порядку перечитай 9-й пост: автор выложил короткий пример (а не всю программу) не для того, чтобы мы нашли тут ошибки, а для того, чтобы пояснили, почему программа падает, да ещё и после исполнения main. А "ни одного предупреждения или ошибки не осталось" относилось к полной программе
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
05.04.2010, 02:42     scanf ? #13
Цитата Сообщение от Evg
И поэтому gcc лезет разбирать форматную строку и проверяет типы последующих аргументов. Хотя компилятор не обязан заниматься такой ерундой.
выше написано, что она не должна проверять

Цитата Сообщение от Evg
Это всего лишь пользовательская фича, но никак не стандарт языка.
lcc тоже выдаёт

так что, либо он не включил предупреждения, либо их там нет

Цитата Сообщение от Evg
А "ни одного предупреждения или ошибки не осталось" относилось к полной программе
это было бы так, если бы он стал запускать программу, которая скомпилировавшись, выдала предупреждение
а он написал, что предупреждений не осталось, он её запустил и она завалилась
и, видимо, он стал это расследовать
и только потом нашёл эту строку
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
05.04.2010, 12:00     scanf ? #14
accept, ещё раз призываю - прочти внимательно пост автора. Там говорилось про древний компилятор 1991 года. Такие предупреждения там не выдаются. То, что их выдаёт gcc и lcc - абсолютно не показательно
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
05.04.2010, 14:47     scanf ? #15
Странная вещь, компилю такой код
C
1
2
scanf("%f");
printf("Hello\n");
шестой билдер отрабатывает без ислючений, VC и Dev выбрасывают исключение только при запуске из среды или из под отладчика, я в недоумении.
M128K145
Эксперт C++
 Аватар для M128K145
8272 / 3491 / 142
Регистрация: 03.07.2009
Сообщений: 10,707
05.04.2010, 15:07     scanf ? #16
kazak, билдер никогда не был нормальной IDE
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
05.04.2010, 15:28     scanf ? #17
Цитата Сообщение от kazak Посмотреть сообщение
шестой билдер отрабатывает без ислючений, VC и Dev выбрасывают исключение только при запуске из среды или из под отладчика, я в недоумении.
В посте 8 я описал причину. Любой код с неинициализированными данными имеет недетерминированное поведение. Т.е. в одной среде он может исполниться так, а в другой сяк. Под "средой" я понимаю не "IDE", а комбинацию "ос + компилятор + библиотеки + переменные окружения и т.п."
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
06.04.2010, 13:54     scanf ? #18
Осознал свою ошибку: аргументы функции заносятся в стек с права на лево и поиск следующих аргументов идет вниз по стеку. Я же почему то решил, что все наоборот и при нехватке какого-либа аргумента, функция непременно наткнется на адрес возврата, запись по которому должна вызывать исключение.
accept
4838 / 3237 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
07.04.2010, 03:42     scanf ? #19
Цитата Сообщение от Evg
accept, ещё раз призываю - прочти внимательно пост автора. Там говорилось про древний компилятор 1991 года. Такие предупреждения там не выдаются. То, что их выдаёт gcc и lcc - абсолютно не показательно
там было два компилятора и в обоих предупреждения не было
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.04.2010, 09:33     scanf ?
Еще ссылки по теме:

scanf() C++
C++ printf/scanf
C++ Scanf

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,126
Записей в блоге: 26
07.04.2010, 09:33     scanf ? #20
Ещё раз говорю. Если в одном компиляторе есть предупреждение, это вовсе не значит, что в другом тоже будет
Yandex
Объявления
07.04.2010, 09:33     scanf ?
Ответ Создать тему
Опции темы

Текущее время: 23:25. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru