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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.67
YurA_280784
Заблокирован
#1

Выделение памяти scanf - C++

23.01.2009, 13:02. Просмотров 1860. Ответов 14
Метки нет (Все метки)

Всем привет
C++
1
2
3
4
5
6
7
8
9
10
11
#include <windows.h>
#include <stdio.h>
 
char * c = (char *)malloc(sizeof(char));
 
void main()
{
    printf("Input string :\r\n");
    scanf("%s",c);
    printf("\r\nstring len %d\r\n",strlen(c));
}
Добавлено через 51 секунду
На первый взгляд кажеться тупизмом в с всего 1 элемент, но ведь сканф делает realloc

Добавлено через 4 минуты 22 секунды
Эй ребята тут програмеры ещё остались, ну млин код компильните мой код
strlen выдаёт на строке abcdef - 6 символов. Всё динамически, нифика в проге изначально не инициализаровано, ну разви что с - єт указатель на 1 символ...

Добавлено через 3 минуты 26 секунд
Эй accept а своим объявлением MAXLINE не загоняешь ли в угол программера, ведь он может ввести строку не более MAXLINE = 1000 символов, ну и где тут динамическое выделение - СТАТИКА!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.01.2009, 13:02
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Выделение памяти scanf (C++):

Выделение памяти, проверка на утечку памяти - C++
Интересуют два вопроса: 1. Правильно ли устроен алгоритм выделения, удаление и запись ячейки памяти? Может быть, есть более простые...

Распределение памяти. Динамическое выделение памяти - C++
an-1 an-2 ... a2

До выделение памяти в С++ - C++
Всем приветик. Вообщем есть некоторые сложности с довыделение памяти... Что я хочу сделать: есть 2-х мерный массив (он ещё и квадратный)....

Выделение памяти - C++
Часто возникает такая проблема, когда конфигурирую проект как Release происходит ошибка выделения памяти (при вызывании new), например...

Выделение памяти - C++
Доброго времени суток. Чтобы выделить память под двумерный массив в такой форме: //n - переменная, M - константа arr = new double...

Выделение памяти - C++
Вот кусок кода, класс и функция добавления в список Класс занимает 64 бита, я добавляю 10 элементов в список - 640 бит Потом отнимаю...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
ISergey
Maniac
Эксперт С++
1373 / 884 / 52
Регистрация: 02.01.2009
Сообщений: 2,653
Записей в блоге: 1
23.01.2009, 13:33 #2
Цитата Сообщение от YurA_280784 Посмотреть сообщение
strlen выдаёт на строке abcdef - 6 символов
а должно сколько???
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
23.01.2009, 13:47 #3
пока пользователь вводит строку она пишется в буфер, потом он нажимает ввод и буфер отправляется программе, количество символов в буфере можно узнать до сохранения буфера

C++
1
2
3
4
5
6
7
8
9
10
 
#include <stdio.h>
 
main()
{
    int s;
    
    scanf("%s", &s);
    return 0;
}
Код
[guest@station tmp]$ cc test.c -o test
[guest@station tmp]$ ./test
abcd
Ошибка сегментирования
[guest@station tmp]$
то есть строку ввести можно, она попадает в буфер а он передаётся проге, узнать сколько символов в него записалось, выделить столько памяти и вызвать функцию сохранения в выделенную область

Добавлено через 6 минут 34 секунды
Эй accept а своим объявлением MAXLINE не загоняешь ли в угол программера
а он всё равно загнан, т.к. не может бесконечную строку ввести, MAXLINE вносит определённости программе
YurA_280784
Заблокирован
23.01.2009, 13:54  [ТС] #4
ISergey - и должно 6 вопрос был есть указатель char *c нужно ччёб он указывал на строку, т.ё указывал на область память в которой буд храниться строка введенная с клавиатуры, в самом начале моего кода с это просто указатель, а вконце это уже указатель на строку и память под с была динамически перераспределена в теле сканф, чё ещё надо то???

Добавлено через 2 минуты 48 секунд
accept речь идёт о том чтобы всё выделялось динамически, ну а скажем через 20 лет программер будет загнан в такой же угол, я имею ввиду объём памяти с которым он может работать???Посуди 30 лет назад 64 кБ было невиданной роскошью для оперативки, а сейчас это пара страниц в вёрде...
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
23.01.2009, 14:39 #5
только если бы была система где нельзя ввести строку в 999 символов рамка на 1000 была бы неправильной, она расширяема под задачи пользователя

C++
1
2
3
4
5
6
7
8
9
10
11
#include <windows.h>
#include <stdio.h>
 
char * c = (char *)malloc(sizeof(char));
 
void main()
{
    printf("Input string :\r\n");
    scanf("%s",c);
    printf("\r\nstring len %d\r\n",strlen(c));
}
в курсе что строка вылезет за границы блока ?
YurA_280784
Заблокирован
23.01.2009, 16:05  [ТС] #6
Я устал повторять СКАНФ делает что-то аналогичное
с = (char *)realloc((void *)c, sizeof(c) + 1);
на каждом символе, так тебе понятней?
Границы блока, я понимаю что строка 6 а вначале strlen(c) = 1, ну а реаллок чё не увеличивает строку, короче я устал, возьми поставь Release версию и запусти прогу, если б были проблемы с памятью появилось бы моё любимое сообщение Память не может быть read
Оно появляется???
Нет, ну так в чём дело...
CheshireCat
23.01.2009, 16:52
  #7

Не по теме:

Где такую траву дают? Отсыпь и мне немного!

XuTPbIu_MuHTAu
Эксперт С++
2224 / 739 / 10
Регистрация: 27.05.2008
Сообщений: 1,508
23.01.2009, 17:10 #8
Цитата Сообщение от YurA_280784 Посмотреть сообщение
Я устал повторять СКАНФ делает что-то аналогичное
с = (char *)realloc((void *)c, sizeof(c) + 1);
на каждом символе, так тебе понятней?
Границы блока, я понимаю что строка 6 а вначале strlen(c) = 1, ну а реаллок чё не увеличивает строку, короче я устал, возьми поставь Release версию и запусти прогу, если б были проблемы с памятью появилось бы моё любимое сообщение Память не может быть read
Оно появляется???
Нет, ну так в чём дело...
А не устал в ответ слышать,что это бред?)

Добавлено через 16 минут 7 секунд
Повторю букварь для тех,кто не в курсе. Сообщение Access violation появляется только при:
1. попытке записи в зарезервированную системой под себя память
2. попытке записи в сегмент кода.
3. попытке исполнения из сегмента данных

Если ты неправильно выделяешь память в куче, ты не получишь никакого violation. Просто будет идти запись в память,помеченную в куче, как свободную. В итоге может случиться переполнение буффера,которое - в лучшем случае - может просто уронить программу. В худшем случае переполнение буффера в куче эксплуатируется не хуже,чем в стеке.
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
23.01.2009, 18:32 #9
Я устал повторять СКАНФ делает что-то аналогичное
C++
1
с = (char *)realloc((void *)c, sizeof(c) + 1);
realloc относится только к куче, scanf записывает по указателю, который может не быть из кучи
если бы scanf так делала, наверное не нужно было бы вообще статических строк делать, а ещё если бы памяти не хватало, scanf завершалась бы с ошибкой, природу которой было бы просто невозможно понять (чего не скажешь ни про одну из функций ANSI C), там все результаты функций строго определены
YurA_280784
Заблокирован
26.01.2009, 11:23  [ТС] #10
Я могу сказать только одно сейчас кидаю Release экзешник, скриншот работы проги и сам код, я устал с тобой спорить accept!!!Может хоть прогу скомпильнёшь, поглядишь успокоишся, а ещё лучше в дэбаге погляди чё ж из себя с представляет после сканф!!!Если говоришь бред хоть проверь а потом гони уже!!!!]-\
Вложения
Тип файла: rar str_tst.exe.rar (14.6 Кб, 13 просмотров)
Тип файла: rar ScrnShot.jpeg.rar (37.1 Кб, 12 просмотров)
Тип файла: rar str_tst.rar (6.5 Кб, 14 просмотров)
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
26.01.2009, 11:50 #11
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
main()
{
    char * c = (char *) malloc(sizeof(char));
    char * n = (char *) malloc(sizeof(char));
    
    printf("Input string :\r\n");
    
    /* здесь я ввёл aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
       и прога вывалилась при free((void *) n); */
    scanf("%s", c);
    printf("\r\nstring len %d\r\n", strlen(c));
    printf("\r\nYour input string :\t%s\r\n", c);
    
    free((void *) c);
    free((void *) n);
    getchar();
    return 0;
}
она пишет за край блока, там память считается незанятой (даже не переполнение буфера играет роль), просто когда память не занята она может быть предоставлена кому-нибудь, то есть ты вводишь строку а через 5 минут полстроки будет перезаписано чем-нибудь запросившим память
а тут я тебе просто показываю как эта строка стирает блок
YurA_280784
Заблокирован
26.01.2009, 15:38  [ТС] #12
А зачем я подчёркивал что кидаю релиз экзешник,
вывалилась прога то у тебя в дебаге, поверь с фри и делит в дебаге часто такие мульки вылетают...

Добавлено через 1 минуту 21 секунду
Релиз пробовал?
В дебаге на сканфе или на фри вываливается, подозреваю на фри

Добавлено через 18 минут 43 секунды
Ставим Build->Set Active configuration release, копилируй, запускай, всё работает!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <windows.h>
#include <stdio.h>
#include <conio.h>
 
void main()
{
    char * c = (char *)malloc(sizeof(char));
    printf("Input string :\r\n");
    scanf("%s",c);
    printf("\r\nstring len %d\r\n",strlen(c));
    printf("\r\nYour input string :\t%s\r\n",c);
    getch();
    free((void *)c);
}
 
Для особо искушённых кидаю прототип сканф, что же делает _input?))))
int __cdecl scanf (
const char *format,
...
)
/*
* stdin 'SCAN', 'F'ormatted
*/
{
int retval;
va_list arglist;
va_start(arglist, format);
_ASSERTE(format != NULL);
_lock_str2(0, stdin);
retval = (_input(stdin,format,arglist));
_unlock_str2(0, stdin);
return(retval);
}
CheshireCat
Эксперт С++
2892 / 1241 / 78
Регистрация: 27.05.2008
Сообщений: 3,368
26.01.2009, 22:54 #13
Угу. Ну, все это, конечно же, замечательно.... Но вот вопрос: если scanf работает так, как ты пишешь, сможешь ли ты объяснить поведение программы? Исходник:
Код
#include <windows.h>  
#include <stdio.h>  
#include <conio.h>  
   
int main()
{
    char * c = (char *)malloc(sizeof(char));
    printf("Input string c:\r\n");
    scanf("%s", c);
    printf("\r\nc string len %d\r\n", strlen(c));
    printf("\r\nYour c string is:\t%s\r\n", c);

    char * n = (char *)malloc(sizeof(char));
    printf("Input string n:\r\n");
    scanf("%s", n);
    printf("\r\nn string len %d\r\n", strlen(n));
    printf("\r\nYour n string is:\t%s\r\n", n);

    printf("\r\nYour c string is:\t%s\r\n", c);

    _getch();
    free((void *)c);
    free((void *)n);
}
Вывод: компилятор GCC 3.4.1, Release:
Input string c:
asdf

c string len 4

Your c string is: asdf
Input string n:
qwerty

n string len 6

Your n string is: qwerty

Your c string is: asdf
Вроде бы все ок, проведем еще эксперимент?
Input string c:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

c string len 95

Your c string is: 1111111111111111111111111111111111111111 /// <--- упс! что за фигня???
Your c string is: 11111111111111111111111111111111111 /// <--- и вот это???
Input string n:
22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

n string len 95

Your n string is: 2222222222222222222222222222222222222222222222222222222222222222222222222222
2222222222222222222

Your c string is: 1111111111111111111111111111111111111111 /// <--- что за фигня выводится? почему три раза???
Your c string is: 1111111111111111111111111111111111111111
Your c string is: 1111111111111111111111111111111111111
Продолжаем: MSVC++ 2005, Release:
c string len 4

Your c string is: asdf
Input string n:
qwerty

n string len 6

Your n string is: qwerty

Your c string is: asdf
Вроде все ок, не так ли? Проведем еще эксперимент:
Input string c:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

c string len 95

Your c string is: 1111111111111111 /// <--- что за фигня?
Your c string is: 1111111111111111
Your c string is: 1111111111111111
Your /// <--- а это что за фигня?
Input string n:
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

n string len 94

Your n string is: 2222222222222222222222222222222222222222222222222222222222222222222222222222
222222222222222222

Your c string is: 1111111111111111 /// <--- что за фигня выводится? ась?
Your c string is: 1111111111111111
Your c string is: 1111111111111111
Your c string is: 1111111111111111
Your c
Ну и до кучи - получаем AV при завершении программы. В Release, подчеркиваю!

Итак, как ты объяснишь полученные экспериментальные результаты?

(То, что в Debug программа вылетает с AV, опустим пока за скобки.... Раз уж ты апеллируешь к Release сборке...)
accept
4821 / 3241 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
26.01.2009, 23:40 #14
А зачем я подчёркивал что кидаю релиз экзешник,
вывалилась прога то у тебя в дебаге, поверь с фри и делит в дебаге часто такие мульки вылетают...
такое бывает когда освобождаешь блок, которого нет, а его нет почему если он был, потому что строка его стёрла, т.к. сканф не делает realloc, а пишет за пределы блока (на соседние поверх); блок был, а на него записалась часть строки, ну и прикинь, здесь ничего не хранилось в блоке, а могло бы, да и строка сама половина становится открытой для записи, потому что находится в свободной памяти
Vourhey
Почетный модератор
6478 / 2253 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
26.01.2009, 23:56 #15
YurA_280784, они правы. scanf не делает realloc. C, в данном случае, не контролирует границ. Ему будет без разницы, какой ты блок malloc'ом выделил. Он просто будет писать дальше.
Знаешь, что я тебе советую сделать. Создай массив из int. Выдели память под один элемент. А потом обратись к пятидесятому элементу, например. У тебя получится это сделать. А к десятитысячному? Да снизойдет на тебя озарение...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.01.2009, 23:56
Привет! Вот еще темы с ответами:

Выделение памяти - C++
Нубский вопрос, но не могу до конца разобраться. Допустим, есть простое определение переменной: int ival = 1024; Когда и как...

Выделение памяти - C++
Платформа и компилятор x64. Установлено 64Gb ОЗУ, 60Gb из них откусил SQL Server. Пытаюсь сделать следующее: struct Dictionary { ...

Выделение памяти - C++
В чём ошибка выделения памяти? Подскажите, друзья! #include &quot;stdafx.h&quot; #include &quot;stdio.h&quot; #include &lt;iostream&gt; #include...

выделение памяти - C++
есть класс множество. необходимо создать класс &quot;правило&quot;, одним из методов которого является добавление множества к соответствующему списку...


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

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

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