Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/3: Рейтинг темы: голосов - 3, средняя оценка - 4.67
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447

Memory Corupting

03.11.2022, 22:56. Показов 674. Ответов 22
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Смотрю различные примеры аллокаторов. Взял примеры вот отсюда https://github.com/mtrebi/memory-allocators

Получаю ошибку на освобождении памяти. HEAP CORRUPTED DETECTED: after normal block.
Запускаю из под VS 2022. Есть мысли что возможно аллоцируется больше чем блок на каждую структуру. Но выделение большего блока памяти не решает проблему а вызывает другую. Код приведен ниже. Либо я устал либо в упор не вижу проблему. Нужна помощь.

header
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
template<class T>
    class StackLinkedList
    {
    public:
        struct Node
        {
            T data;
            Node* next;
        };
        Node* head;
        StackLinkedList() = default;
        StackLinkedList(StackLinkedList&) = delete;
        ~StackLinkedList() { if (head) delete head; }
        void push(Node* newNode)
        {
            newNode->next = head;
            head = newNode;
        }
        Node* pop()
        {
            Node* top = head;
            head = head->next;
            return top;
        }
    };
 
    class ListAllocator
    {
    public:
        ListAllocator(const std::size_t totalSize, const std::size_t chunkSize);
        ~ListAllocator();
        void* Allocate(std::size_t blockSize);
        void Deallocate(void* p, ::std::size_t blockSize);
        void Init();
    private:
        struct FreeHeader {};
        using Node = StackLinkedList<FreeHeader>::Node;
        StackLinkedList<FreeHeader> mFreeList;
 
        void* mStartPtr;
        std::size_t mChunkSize;
        std::size_t mTotalSize;
        std::size_t mUsed;
        std::size_t mPeak;
    };
source
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
ListAllocator::ListAllocator(const std::size_t totalSize, const std::size_t chunkSize) 
        : mFreeList()
        , mChunkSize(chunkSize)
        , mTotalSize(totalSize)
        , mUsed(0)
        , mPeak(0)
    {}
 
    ListAllocator::~ListAllocator()
    {
        free(mStartPtr);
    }
 
    void* ListAllocator::Allocate(std::size_t blockSize)
    {
        Node* freePosition = mFreeList.pop();
        mUsed += mChunkSize;
        mPeak = std::max(mPeak, mUsed);
        return (void*)freePosition;
    }
 
    void ListAllocator::Deallocate(void* p, ::std::size_t blockSize)
    {
        mUsed -= mChunkSize;
        mFreeList.push((Node*)p);
    }
 
    void ListAllocator::Init()
    {
        mStartPtr = malloc(mTotalSize);
        const int nChunks = mTotalSize / mChunkSize;
        for (int i = 0; i < nChunks; ++i)
        {
            const std::size_t shift = i * mChunkSize;
            std::size_t address = (std::size_t)mStartPtr + shift;
            t = shift;
            mFreeList.push((Node*)address);
        }
    }
вызов
C++
1
2
3
        CustomAllocator::ListAllocator la(UCHAR_MAX * sizeof(std::size_t), sizeof(std::size_t));
        la.Init();
        la.~ListAllocator();
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
03.11.2022, 22:56
Ответы с готовыми решениями:

Out of memory
Недавно решил освоить графику в с++, и при прорисовке изображения на канве заметил, что оно занимает память. По таймеру каждые 100...

Memory Manager
Добрый день, после прочтения темы https://www.cyberforum.ru/cpp-beginners/thread1399246.html заинтересовался: стоит ли писать такой...

Memory Bomb
помогите пожалуйста решить лабораторную работу))))заранее спасибо) Напишите программу, которая выделяет 200 раз по 200 мегабайт (память...

22
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:10
Цитата Сообщение от BaredJJ Посмотреть сообщение
la.~ListAllocator();
Что это? Вызывать вручную деструктор нужно только для объектов, которые вручную конструировались (через placement-new).
Короче, рановато пока для аллокаторов, сперва основы языка подтянуть нужно.
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:14  [ТС]
Да это я его уже руками вызывал. Он когда из поля видимости цикла выходит и объект уничтожается в деструктор заходит.
И на free естественно вываливается. Та же проблема у меня была и с аллокатором от Александреску.

Добавлено через 2 минуты
Т.е. если я использовал free в Chunk от SmallObjectAllocator при релизе у меня память тоже кораптилась, но на delete[] проблем не было.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:14
Цитата Сообщение от BaredJJ Посмотреть сообщение
И на free естественно вываливается.
А вот это что такое? Почему тут delete?
Цитата Сообщение от BaredJJ Посмотреть сообщение
~StackLinkedList() { if (head) delete head; }
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:17  [ТС]
Это уже тоже пытался посмотреть может он список не чистит. Изначально этого не было. Тут уже после заливки нельзя отредактировать было

Добавлено через 1 минуту
C++
1
2
3
4
5
6
7
8
9
10
       
 mStartPtr = malloc(mTotalSize);
        const int nChunks = mTotalSize / mChunkSize;
        for (int i = 0; i < nChunks; ++i)
        {
            const std::size_t shift = i * mChunkSize; //For test
            std::size_t address = (std::size_t)mStartPtr + shift;
            t = shift;//For test
            mFreeList.push((Node*)address);
        }
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:19
Цитата Сообщение от BaredJJ Посмотреть сообщение
Это уже тоже пытался посмотреть может он список не чистит.
Кто "он"? Что посмотреть?
Цитата Сообщение от BaredJJ Посмотреть сообщение
Изначально этого не было.
А зачем появилось?
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:19  [ТС]
Это вот я тоже для того чтобы посмотреть какое смещение от начального адреса было. Посмотрел sizeof самой структуры 16, но вот для указателя на ноду 8. Ну и newNode тоже 8 весит
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:20
Цитата Сообщение от BaredJJ Посмотреть сообщение
Получаю ошибку на освобождении памяти. HEAP CORRUPTED DETECTED: after normal block.
Вот на этом delete и получаешь ошибку.
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:27  [ТС]
Вот на этом delete и получаешь ошибку.
Вот не похоже. Удалил его. Тоже самое.

Добавлено через 2 минуты
вызов
C++
1
2
3
4
5
    for (int i = 0; i < 10; ++i)
    {
        CustomAllocator::ListAllocator la(UCHAR_MAX * sizeof(std::size_t), sizeof(std::size_t));
        la.Init();
    }
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
template<class T>
    class StackLinkedList
    {
    public:
        struct Node
        {
            T data;
            Node* next;
        };
        Node* head;
        StackLinkedList() = default;
        StackLinkedList(StackLinkedList&) = delete;
        void push(Node* newNode)
        {
            newNode->next = head;
            head = newNode;
        }
        Node* pop()
        {
            Node* top = head;
            head = head->next;
            return top;
        }
    };
 
    class ListAllocator
    {
    public:
        ListAllocator(const std::size_t totalSize, const std::size_t chunkSize);
        ~ListAllocator();
        void* Allocate(std::size_t blockSize);
        void Deallocate(void* p, ::std::size_t blockSize);
        void Init();
    private:
        struct FreeHeader {};
        using Node = StackLinkedList<FreeHeader>::Node;
        StackLinkedList<FreeHeader> mFreeList;
 
        void* mStartPtr;
        std::size_t mChunkSize;
        std::size_t mTotalSize;
        std::size_t mUsed;
        std::size_t mPeak;
    };
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
 ListAllocator::ListAllocator(const std::size_t totalSize, const std::size_t chunkSize) 
        : mFreeList()
        , mChunkSize(chunkSize)
        , mTotalSize(totalSize)
        , mUsed(0)
        , mPeak(0)
    {}
 
    ListAllocator::~ListAllocator()
    {
        free(mStartPtr);
    }
 
    void* ListAllocator::Allocate(std::size_t blockSize)
    {
        Node* freePosition = mFreeList.pop();
        mUsed += mChunkSize;
        mPeak = std::max(mPeak, mUsed);
        return (void*)freePosition;
    }
 
    void ListAllocator::Deallocate(void* p, ::std::size_t blockSize)
    {
        mUsed -= mChunkSize;
        mFreeList.push((Node*)p);
    }
 
    void ListAllocator::Init()
    {
        mStartPtr = malloc(mTotalSize);
        const int nChunks = mTotalSize / mChunkSize;
        for (int i = 0; i < nChunks; ++i)
        {
            const std::size_t shift = i * mChunkSize;
            std::size_t address = (std::size_t)mStartPtr + shift;
            mFreeList.push((Node*)address);
        }
    }
Тоже самое

Добавлено через 1 минуту
Тут как бы код прям вроде один в один как на гите, да и создаю объект правильно. Я вот не понимаю что free как то не работает, может есть какие то подводные камни?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:28
Цитата Сообщение от BaredJJ Посмотреть сообщение
Вот не похоже. Удалил его. Тоже самое.
Похоже или не похоже, быть его там не должно!
А еще член head у тебя не инициализирован. И остального гомнокода ты не предоставил.
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:34  [ТС]
Хммм. Интересно. Но вот сколько я вижу head ставится в push. А остального то перфектного кода и нет.

Добавлено через 45 секунд
Я же его специально и сократил до того чтобы понять в чем проблема.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:36
Лучший ответ Сообщение было отмечено BaredJJ как решение

Решение

Цитата Сообщение от BaredJJ Посмотреть сообщение
const std::size_t shift = i * mChunkSize;
            std::size_t address = (std::size_t)mStartPtr + shift;
            mFreeList.push((Node*)address);
Если закрыть глаза на многое, то остается проблема, что размер чанка у тебя меньше размера нода, ты портишь память.
1
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:46  [ТС]
Как это понять. Я вот полагаюсь на sizeof и он мне выводит что размер Node* равен 8. Мы же по сути и не создаем сами ноды а по сути интерпретируем память как Node*

Добавлено через 5 минут
Похоже понял. Я тогда не понимаю зачем выкладывать не рабочий аллокатор в доступ
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.11.2022, 23:46
Цитата Сообщение от BaredJJ Посмотреть сообщение
размер Node* равен 8
Но у тебя sizeof(Node*) != sizeof(Node)! Член next, который меняется в push, расположен по адресу address + 8.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
03.11.2022, 23:47
Цитата Сообщение от BaredJJ Посмотреть сообщение
Я вот полагаюсь на sizeof и он мне выводит что размер Node* равен 8.
В какой разрядности компилируете?
На 64 битах он никак не может быть 8, потому что 8 занимает только указатель, а член data у вас равен 1, что в сумме приведет к выравниванию до 16. Т.е. на 64 битах sizeof Node равен 16.
0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
03.11.2022, 23:53  [ТС]
Понятно. Он рабочий но только на объектах больше 16 байт. Нужно чтобы размер одного чанка был больше или равен размеру ноды.

Добавлено через 3 минуты
В какой разрядности компилируете?
На 64 битах он никак не может быть 8, потому что 8 занимает только указатель, а член data у вас равен 1, что в сумме приведет к выравниванию до 16. Т.е. на 64 битах sizeof Node равен 16.
Да да, тут все верно. Я писал именно о размере указателя.

Но у тебя sizeof(Node*) != sizeof(Node)! Член next, который меняется в push, расположен по адресу address + 8.
Согласен. не спорю.

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

Добавлено через 41 секунду
И спасибо за помощь. Теперь хоть спать спокойнее буду.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
04.11.2022, 00:00
Цитата Сообщение от BaredJJ Посмотреть сообщение
Он рабочий но только на объектах больше 16 байт.
Он условно рабочий только на размерах чанка 16. Не больше.
Потому что при большем размере начнет затираться указатель next.
Чтобы это починить нужно поменять местами data и next и соответственно исправить выдачу адреса пользователю аллокатора.

Добавлено через 3 минуты
Цитата Сообщение от BaredJJ Посмотреть сообщение
А то вот от Александреску работает хуже чем дефолтный если замеры просто на пару проходов полного заполнения и удаления вектора делать.
Любые замеры вне реального кода будут врать.
Если у вас нет задачи, уже реально сделанного и работающего кода, в котором после профилирования выяснилась потребность в смене аллокатора, и на котором можно проверить работу вашего аллокатора, то нечего даже садиться его писать.

Добавлено через 1 минуту
Аллокатор пишется под задачу. Замеры в вакууме, без задачи, будут врать. Если есть задача и есть удачно написанный под нее аллокатор, то вы увидите эффект на тестах. Все остальные варианты останутся лишь злостными инсинуациями.
1
04.11.2022, 00:00

Не по теме:

Цитата Сообщение от BaredJJ Посмотреть сообщение
А то вот от Александреску работает хуже чем дефолтный если замеры просто на пару проходов полного заполнения и удаления вектора делать.
Использовать для вектора пул-аллокатор неуместно.
Более того, в современных рантаймах с++ стандартные new/delete настолько хорошо оптимизированны, что не уступают в однопоточных приложениях по производительности даже std::pmr::monotonic_buffer_resource (это что-то вроде стекового аллокатора).

0
 Аватар для BaredJJ
19 / 18 / 7
Регистрация: 16.05.2017
Сообщений: 447
04.11.2022, 09:42  [ТС]
Он условно рабочий только на размерах чанка 16. Не больше.
Потому что при большем размере начнет затираться указатель next.
Чтобы это починить нужно поменять местами data и next и соответственно исправить выдачу адреса пользователю аллокатора.
Вот тут не совсем понял. Когда нода отдается, то вроде же не нужно сохранять никакой указатель на следующий элемент и если к примеру у нас объект 16 или более байт, то в любом случае next перезатрется как их местами не меняй. Ведь в месте вызова память будет интерпретироваться как другой объект.

Аллокатор пишется под задачу. Замеры в вакууме, без задачи, будут врать. Если есть задача и есть удачно написанный под нее аллокатор, то вы увидите эффект на тестах. Все остальные варианты останутся лишь злостными инсинуациями.
А можно тут какие ни будь примеры. Я просто всегда полагал что есть набор стандартных решений на те или иные случаи, а звучит так, что везде просто набор своих хаков.

Использовать для вектора пул-аллокатор неуместно.
Лучше наверное на списках попробовать. Или я не прав?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
04.11.2022, 11:43
Цитата Сообщение от BaredJJ Посмотреть сообщение
набор стандартных решений на те или иные случаи
Написание своего аллокатора - это уже по определению нестандартное решение. Если вы к этому пришли, значит у вас есть веские причины. Все стандартные решения уже давно описаны в стандартных аллокаторах.

Цитата Сообщение от BaredJJ Посмотреть сообщение
А есть какие ни будь актуальные статьи по аллокаторам для небольших объектов? А то вот от Александреску работает хуже чем дефолтный если замеры просто на пару проходов полного заполнения и удаления вектора делать.
Это вот звучит как: "я просто взял кейс от балды, начал проверять и оказалось, что в этом кейсе аллокатор Александреску не работает хорошо, поэтому я делаю вывод, то аллокатор неакутальный, и надо искать другой, желательно со статьей, где все разжевывается.". А я вам говорю, что не будет этого, потому что это уже территория "хаков". Инженерно-исследовательская работа в поле, на реальных задачах. Вот и все. Тут нет и не может быть никаких стандартных решений.

Цитата Сообщение от BaredJJ Посмотреть сообщение
гда нода отдается, то вроде же не нужно сохранять никакой указатель на следующий элемент
Да, это верно, я неправильно посмотрел вчера. У вас же нода при аллокации удаляется из пула, а не добавляется (технически может и добавляться, т.е. это будет пул занятых чанков и тогда цитата про затирание next будет верной).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.11.2022, 11:43
Помогаю со студенческими работами здесь

vector memory
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; using namespace std; template &lt;typename T&gt; class vector { T* m_arr; int...

memory can't be 'written'
Помогите найти ошибку. При компиле ничего не выскакивает. Когда запускаю программу - ошибка. Программа-переводчик из двоичной системы...

memory leaks | Деструктор
#ifndef INTEG_H_ #define INTEG_H_ #include &lt;iostream&gt; using namespace std; class integer{ private: int value; int...

Unable to read memory
Явных ошибок нет, а в чем проблема понять не могу. Буду премного благодарен за разъяснение.

Custom memory manager
в образовательных целях решил написать свой менеджер памяти class memory_pool { typedef unsigned char byte; struct free_space...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
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