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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 19, средняя оценка - 4.74
Mikant
1263 / 935 / 56
Регистрация: 08.12.2009
Сообщений: 1,299
#1

scanf ? - C++

02.04.2010, 23:41. Просмотров 2485. Ответов 19
Метки нет (Все метки)

господа, подскажите пожалуйста, почему после этого в 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 - C++
можна прочитать несколько значений использав всего раз scanf например : scanf (&quot;%d %d&quot;,&amp;a,&amp;b); ? - правильно ли это...

scanf() - C++
Всем привет! Вот маленький тестовый пример #include &lt;stdio.h&gt; int i; int main() { printf(&quot;Enter value:...

Scanf - C++
#include &lt;iostream&gt; #include &lt;string&gt; #include &lt;cstdio&gt; #include &lt;cstdlib&gt; using namespace std; int maska(string a,string...

Функция scanf() - C++
//--------------------------------------------------------------------------- #include &lt;vcl.h&gt; #include &lt;stdio.h&gt; #include...

fprintf scanf - C++
Помогите с кодом Хочу сделать считывание с файла и вывод в файл output input #include &lt;stdio.h&gt; #include &lt;io.h&gt; #include...

Scanf в Eclipse - C++
Всем привет) Подскажите пожалуйста как мне в Eclipse ввести какие-то данные в scanf() Заранее спасибо!

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
M128K145
Эксперт С++
8286 / 3505 / 143
Регистрация: 03.07.2009
Сообщений: 10,706
03.04.2010, 00:02 #2
потому что вы его неправильно используете.
Это вопрос аналогичен такому
почему код
C++
1
2
int a = 0;
++a;
работает, а
C++
1
2
int a;
++a;
бросает эксепшен
easybudda
Модератор
Эксперт CЭксперт С++
9530 / 5523 / 932
Регистрация: 25.07.2009
Сообщений: 10,608
03.04.2010, 00:31 #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
1263 / 935 / 56
Регистрация: 08.12.2009
Сообщений: 1,299
03.04.2010, 00:50  [ТС] #4
M128K145, не, ну тут, понятное дело, непроинициализированная переменная... а у меня куда считанный дабл записывается? и когда?

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

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

Добавлено через 3 минуты
M128K145, тем более ++a выбрасывает исключение в рантайме, а моя конструкция - нет... зараза...
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
03.04.2010, 05:06 #5
Исключение выбивает потому что происходит попытка записи в секцию кода, которая по умолчанию имеет атрибут только чтение.
Mikant
1263 / 935 / 56
Регистрация: 08.12.2009
Сообщений: 1,299
03.04.2010, 12:45  [ТС] #6
kazak, а почему запись в эту секцию происходит ПОСЛЕ main??
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
03.04.2010, 17:53 #7
А почему ты решил, что это происходит после мэйна?
Evg
Эксперт CАвтор FAQ
17633 / 5857 / 378
Регистрация: 30.03.2009
Сообщений: 16,156
Записей в блоге: 26
03.04.2010, 18:53 #8
Цитата Сообщение от Mikant Посмотреть сообщение
почему вообще вылетает
В scanf'е ты указал "%lf". Сие означает, что следующим параметром ожидается указатель на double. Но указатель ты не подал. Поэтому в том месте памяти, где среди параметров ожидался указатель, реально пришёл мусор (неинициализированное значение). Этот мусор далее начал трактоваться как указатель, по которому внутри scanf'а начала выполняться запись введённого значения. С вероятностью, близкой к единице, такой код сломается

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

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

ззы. если всю программу трассировать по шагам - тот же эффект, соответственно
Evg
Эксперт CАвтор FAQ
17633 / 5857 / 378
Регистрация: 30.03.2009
Сообщений: 16,156
Записей в блоге: 26
03.04.2010, 20:39 #10
Значит такой кривой scanf затёр в памяти что-то в системной части и после завершения main сломался завершающий код
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
04.04.2010, 08:33 #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
Эксперт CАвтор FAQ
17633 / 5857 / 378
Регистрация: 30.03.2009
Сообщений: 16,156
Записей в блоге: 26
04.04.2010, 14:02 #12
accept, с gcc сравнивать не совсем корректно, потому как gcc выдаёт warning не совсем честным способом: он банально "узнаёт" функцию. Старые версии gcc делали это тупо по имени, а в современных версиях в инклюдах у функций printf (и всей группы), scanf (и всей группы) есть некий атрибут (не помню точно как он называется). говорящий о том, что прототип функции соотвествует действию printf'а и scanf'а соответсвенно. И поэтому gcc лезет разбирать форматную строку и проверяет типы последующих аргументов. Хотя компилятор не обязан заниматься такой ерундой. Это всего лишь пользовательская фича, но никак не стандарт языка. Прочие компиляторы как правило этим не заморачиваются и предупреждений не выдают.

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

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

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

Цитата Сообщение от Evg
А "ни одного предупреждения или ошибки не осталось" относилось к полной программе
это было бы так, если бы он стал запускать программу, которая скомпилировавшись, выдала предупреждение
а он написал, что предупреждений не осталось, он её запустил и она завалилась
и, видимо, он стал это расследовать
и только потом нашёл эту строку
Evg
Эксперт CАвтор FAQ
17633 / 5857 / 378
Регистрация: 30.03.2009
Сообщений: 16,156
Записей в блоге: 26
05.04.2010, 12:00 #14
accept, ещё раз призываю - прочти внимательно пост автора. Там говорилось про древний компилятор 1991 года. Такие предупреждения там не выдаются. То, что их выдаёт gcc и lcc - абсолютно не показательно
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
05.04.2010, 14:47 #15
Странная вещь, компилю такой код
C
1
2
scanf("%f");
printf("Hello\n");
шестой билдер отрабатывает без ислючений, VC и Dev выбрасывают исключение только при запуске из среды или из под отладчика, я в недоумении.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.04.2010, 14:47
Привет! Вот еще темы с ответами:

Scanf в цикле - C++
#include&lt;stdio.h&gt; #include&lt;stdlib.h&gt; #include&lt;math.h&gt; int main() { int n,i,k; double a,r;

scanf, char - C++
Есть нубский вопрос... char * str=new char; //char str; scanf(&quot;%s&quot;,str); char chr; scanf(&quot;%c&quot;,&amp;chr); В этом коде chr хавает...

printf/scanf - C++
Возник вопрос. int main(void) { printf(&quot;Hello world&quot;); } Что происходит здесь? Подключение в дебаге хедера &lt;stdio.h&gt; или...

Разногласия с scanf - C++
Фрагмент кода: int x, y, xmod; printf(&quot;Введите X:&quot;); scanf(&quot;%d&quot;,&amp;x); Ругается на scanf(&quot;%d&quot;,&amp;x) и говорит: ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
05.04.2010, 14:47
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru