Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/12: Рейтинг темы: голосов - 12, средняя оценка - 4.83
 Аватар для tes
0 / 0 / 0
Регистрация: 19.01.2011
Сообщений: 3

И снова malloc...

07.06.2011, 16:33. Показов 2621. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!

Читаю книгу "Герберт Шилдт - самоучитель С++"
В нём такое задание:
Code
1
2
3
Измените класс stack так, чтобы память для стека выделялась динамически.
При этом длина стека должна задаваться параметром конструктора. 
(Не забудьте освободить эту память с помощью деструктора.)
Я выполнил в таком виде:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
#define max_size 100
 
class stack{
     char *stck;
     int tos;
     char who;
public:
     stack (char c, int pam);
     ~stack();
     void push(char ch);
     char pop(); 
};
 
stack::stack(char c, int pam)
{
     tos = 0;
     who = c;
     stck = (char*) malloc(pam);
     cout << pam << endl;
     if (!stck)
     {
          cout << "Ошибка выделения памяти" << endl;
          exit(1);
     }    
}
 
void stack::push(char ch)
{
     if (tos >= max_size){
          cout << "Стек " << who << " полон." << endl;
          return;
     }
 
     stck[tos] = ch;
     ++tos;
}
 
char stack::pop()
{
     if (tos == 0) {
          cout << "Стек " << who << " пуст." << endl;
          return 0x20;
     }
     else
     {
          --tos;
          return  stck[tos];
     };
}
 
stack::~stack()
{
     cout << "Освобождение памяти" << endl;
     free(stck);              
}
 
int main()
{
    stack s1('A',0), s2('B',0);
    int i;
    
    s1.push('a');
    s2.push('x');
    s1.push('b');
    s2.push('y');
    s1.push('c');
    s2.push('z');
    
 
    for (i = 0; i < 5; ++i) cout << "Символ из стека s1: " << s1.pop() << endl; //Для проверки запихиваем 3 , вытаскиваем 5
    for (i = 0; i < 5; ++i) cout << "Символ из стека s2: " << s2.pop() << endl;
 
    return EXIT_SUCCESS;
}
Потом меня взяли сомнения по поводу выделения памяти и я решил посмотреть ответы данные в конце книги, как оказалось там память выделяется так же...

Так собственно вопрос, почему когда я ставлю stack s1('A',0), s2('B',0);, у меня всё проходит нормально? Почему УМВР? ЧЯДН? Может кто нибудь прояснить ситуацию?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
07.06.2011, 16:33
Ответы с готовыми решениями:

И снова динамическая память, malloc и free в конструкторе и деструкторе
Короче есть, класс, который например хранит строку, я его храню в структуре, после я выдиляю динамическу память пот эту структуру и копирую...

Как сделать чтобы таймер дойдя до 0 стартовал снова и снова?
Здравствуйте :) Как сделать чтобы таймер дойдя до 0 стартовал снова и снова? TimerSec = 59; TimerMin = 6; for(int i = TimerSec;...

Malloc vs new
Здравствуйте. Вникаю в ручное управление памятью. Абзац из книги &quot;C++ для профессионалов&quot; не совпадает с моим представлением...

13
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
07.06.2011, 17:06
Цитата Сообщение от tes Посмотреть сообщение
Потом меня взяли сомнения по поводу выделения памяти
Тебя сомнения одолели правильные и с памятью работа сделана некорректно. В качестве pam ты всюду подаёшь 0. Когда 0 подаётся в malloc, то во многих реализациях номинально выделяется 1 байт. Далее malloc выделяет выровненную память, в слчае i386 она выравнивается на 16 байт (или на 8). Т.е. при вызове malloc(0) у тебя реально выделяется на машине 8 или 16 байт. При этом в стек ты суёшь только по 3 элемента, а потому у тебя ошибка не проявляется

Модифицируй немного свою программу. В main у тебя стеки создаются сначала s1, потом s2. Поменяй их местами. И сделай не по 3 push'а, а по 17. При таком раскладе у меня на твоём коде программа сломалась

Добавлено через 11 секунд
Цитата Сообщение от tes Посмотреть сообщение
Почему УМВР? ЧЯДН?
Цэ шо?

Добавлено через 13 секунд
А... понял
2
 Аватар для tes
0 / 0 / 0
Регистрация: 19.01.2011
Сообщений: 3
07.06.2011, 21:04  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
И сделай не по 3 push'а, а по 17. При таком раскладе у меня на твоём коде программа сломалась
Очень странно программа себя ведёт... Сколько malloc "по умолчанию" выделяет не совсем понятно...

Вот немного переписал программу:
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
#define max_size 100
 
class stack{
     char *stck;
     unsigned int tos;
     char who;
public:
     stack (char c, int pam);
     ~stack();
     void push(char ch);
     char pop(); 
};
 
stack::stack(char c, int pam)
{
     tos = 0;
     who = c;
     stck = (char*) malloc(pam);
     cout << pam << endl;
     if (!stck)
     {
          cout << "Ошибка выделения памяти" << endl;
          exit(1);
     }    
}
 
void stack::push(char ch)
{
     if (tos >= max_size){
          cout << "Стек " << who << " полон." << endl;
          return;
     }
 
     stck[tos] = ch;
     ++tos;
}
 
char stack::pop()
{
     if (tos == 0) {
          cout << "Стек " << who << " пуст." << endl;
          return 0x20;
     }
     else
     {
          --tos;
          return  stck[tos];
     };
}
 
stack::~stack()
{
     cout << "Освобождение памяти" << endl;
     free(stck);              
}
 
int main()
{
    stack s1('A',85), s2('B',85), s3('C',85);
    unsigned int i;
    
    cout << "В стек A->>>>" << endl;
    for (i = 0; i < max_size; ++i) s1.push('f');
 
    cout << "В стек B->>>>" << endl;
    for (i = 0; i < max_size; ++i) s2.push('g');    
 
    cout << "В стек C->>>>" << endl;
    for (i = 0; i < max_size; ++i) s3.push('h'); 
    
    cout << "Из стека A->>>>" << endl;
    for (i = 0; i < max_size; ++i) 
    {
        if ((i % 100) != 99)
           if (s1.pop() == 'f') cout << "*";
           else cout << "x";
        else
           if (s1.pop() == 'f') cout << "*" << endl;
           else cout << "x" << endl;
    }
    
    cout << "Из стека B->>>>" << endl;
    for (i = 0; i < max_size; ++i) 
    {
        if ((i % 100) != 99)
           if (s2.pop() == 'g') cout << "*";
           else cout << "x";
        else
           if (s2.pop() == 'g') cout << "*" << endl;
           else cout << "x" << endl;
    }
 
    cout << "Из стека C->>>>" << endl;
    for (i = 0; i < max_size; ++i) 
    {
        if ((i % 100) != 99)
           if (s3.pop() == 'h') cout << "*";
           else cout << "x";
        else
           if (s3.pop() == 'h') cout << "*" << endl;
           else cout << "x" << endl;
    }
    
    cout << endl << endl;
    return EXIT_SUCCESS;
}
Вроде бы она в таком случае ( stack s1('A',85), s2('B',85), s3('C',85) ) должна выделить 16 + 85 или 8 + 85, но нет ведь....

https://www.cyberforum.ru/atta... 1307466054
Миниатюры
И снова malloc...  
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
07.06.2011, 22:57
Цитата Сообщение от tes Посмотреть сообщение
Сколько malloc "по умолчанию" выделяет не совсем понятно...
Чтобы не думать о том, что там по умолчанию, надо работать правильно и не задумываться о таких вопросах. Т.е. выделять памяти столько, сколько надо, а не в количестве 0 байт.

Цитата Сообщение от tes Посмотреть сообщение
должна выделить 16 + 85 или 8 + 85
Наверное я не так выразился. Память, возвращаемая malloc'ом, всегда должна быть выровнена на 8 байт (или 16, но пусть будет 8). Это означает, что после того, как ты выделил 1 байт, то последующий вызов malloc'а пропустит 7 байт, чтобы следующий адрес был так же кратен 8 байтам. В итоге те 7 байт останутся неиспользоваными. Но при работе с указателем от первого вызова в эти ненужные 7 байт ты можешь нормально обращаться и программа не упадёт (хотя номинально код будет ошибочным). Ну и в таком предположении malloc всегда как бы выделяет количество байт памяти, округлённое до кратности 8 (с округлением в большую сторону). Т.е. если в malloc подать значения от 1 до 8, то всё равно как бы будет выделено 8 байт (выделено будет столько, сколько нужно плюс неиспользуемый хвост). Если подать значение от 9 до 16, то будет выделено 16 байт и т.п.

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

Можешь ещё немного тут почитать: https://www.cyberforum.ru/cpp-... ost1671703

Что касается твоего кода, то он уже почти правильный. Только в 35 строке надо сравнивать не с max_size, а со значением pam, которое ты подал в конструктор (понятно, что его надо сохранить в экземпляре класса)
2
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
07.06.2011, 23:33
Цитата Сообщение от Evg Посмотреть сообщение
чтобы следующий адрес был так же кратен 8 байтам
А с чем это связанно? Я читал просто про 2 байта (т.е. чтоб адрес был кратен 2).
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
07.06.2011, 23:40
Цитата Сообщение от Kastaneda Посмотреть сообщение
А с чем это связанно? Я читал просто про 2 байта (т.е. чтоб адрес был кратен 2).
Указатель, возвращаемый malloc'ом должен быть приводим к указателю на любой базовый класс. Другими словами, результат malloc'а должен быть выровнен на максимальное из выравниваний среди базовых типов (по сути на выравнивание long double'а). Это как минимум. На i386 дополнительно есть какие-то магические операции с памятью, которые требуют адреса, выровненного на 8 байт. Если я ничего не напутал

Про 2 байта, которые ты читал - это скорее всего ещё в старых книгах, где ещё DOS'овские соглашения были описаны.
1
 Аватар для OstapBender
594 / 532 / 76
Регистрация: 22.03.2011
Сообщений: 1,585
07.06.2011, 23:44
Evg, по-моему malloc(0) это UB и никакие правила тут не действуют...
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
07.06.2011, 23:46
Цитата Сообщение от OstapBender Посмотреть сообщение
Evg, по-моему malloc(0) это UB и никакие правила тут не действуют...
А я что-то другое сказал?

Цитата Сообщение от Evg
Когда 0 подаётся в malloc, то во многих реализациях номинально выделяется 1 байт
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
07.06.2011, 23:46
malloc с классами? оригинально
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
07.06.2011, 23:47
Цитата Сообщение от ForEveR Посмотреть сообщение
malloc с классами? оригинально
Когда человек учится и сам разбирается - это более чем нормально
0
 Аватар для OstapBender
594 / 532 / 76
Регистрация: 22.03.2011
Сообщений: 1,585
07.06.2011, 23:51
Ага, увидел
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
08.06.2011, 00:05
Вот другая реализация malloc'а. Если в вызывать malloc(0), то будет возвращать ZEROSIZEPTR - это вообще получается некая константа, видимо такое значение возвращается из тех соображений, чтобы обращения по такому адресу вызывали слом программы. Там так же есть malloc_minsize - некий минимальный выделяемый кусок. В этой (да и в большинстве других реализаций) получается, что malloc'ать память маленькими кусочками - выходит очень неэффективно, а потому любая мало-мальски серьёзная программа содержит свой менеджер памяти, который строится поверх malloc'а
1
08.06.2011, 10:09

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
Указатель, возвращаемый malloc'ом должен быть приводим к указателю на любой базовый класс. Другими словами, результат malloc'а должен быть выровнен на максимальное из выравниваний среди базовых типов (по сути на выравнивание long double'а)
Точно, мог бы сам догаться)
Цитата Сообщение от Evg Посмотреть сообщение
Про 2 байта, которые ты читал - это скорее всего ещё в старых книгах, где ещё DOS'овские соглашения были описаны.
Да, это я когда асм под ДОС осваивал, тогда и читал.

0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
 Аватар для easybudda
12843 / 7592 / 1766
Регистрация: 25.07.2009
Сообщений: 13,973
15.07.2011, 19:37
Цитата Сообщение от Evg Посмотреть сообщение
Когда 0 подаётся в malloc, то во многих реализациях номинально выделяется 1 байт. Далее malloc выделяет выровненную память, в слчае i386 она выравнивается на 16 байт (или на 8). Т.е. при вызове malloc(0) у тебя реально выделяется на машине 8 или 16 байт.
Интересно стало...
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
 
int main(void){
    char * p;
    
    if ( ! ( p = malloc(0) ) ){
        fprintf(stderr, "Nicht gemacht, kaput!\n");
        exit(1);
    }
    
    printf("p has %d bytes allocated.\n", malloc_usable_size(p));
    
    free(p);
    exit(0);
}
Code
1
2
3
4
andrew@debnout:~/cpp/system$ gcc -o p0 p0.c 
andrew@debnout:~/cpp/system$ ./p0
p has 12 bytes allocated.
andrew@debnout:~/cpp/system$
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.07.2011, 19:37
Помогаю со студенческими работами здесь

new на malloc
Измените выделение памяти на C - malloc,и почему у меня не открывает текстовый файл? #include &quot;stdafx.h&quot; #include...

new vs malloc
Чем new безопаснее(или лучше?) malloc?

malloc в С++
Подскажите пожалуйста как в данной программе выделить динамическую память с помощью malloc для объекта #include &lt;iostream&gt; ...

new, malloc,
Добрый день. При роботе с дин. памяттю в конец выделяемой памяти добавляеться какойто бред, чтото топа &quot;&lt;&lt;&lt;ЮЮЮээээ&quot;....

New и malloc
Если смотреть на выделение памяти для арифметических типов уступает ли функций new malloc'у в скорости? Если да, то насколько это критично?


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru