Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

утечек памяти нет, а New выбрасывает Exception-ы после долгой работы. почему ?

1.0K
13 февраля 2006 года
diesel_den
169 / / 22.12.2005
Что бы это могло быть? Какие операции впринципе могут приводить к краху ТАКИХ ВАЖНЫХ системных функций ? Это же, например, не попытка обращения к памяти, которая потерпит крах при недопустимом адресе. Я же только говорю, что мне нужно немножко памяти, которой у системы ещё прудь пруди. С чего бы это вдруг система не можут выделить немножко (байт 100) памяти ?
Страницы:
398
17 февраля 2006 года
Alexandoros
630 / / 21.10.2005
1) А как я в delete узнаю, скока я байт освобождаю, если передаётся в него токо указатель?

В дебуг режиме -

Код:
#include "stdafx.h"
#include <new>

typedef struct _CrtMemBlockHeader1
{
    struct _CrtMemBlockHeader1 * pBlockHeaderNext;
    struct _CrtMemBlockHeader1 * pBlockHeaderPrev;
    char *                      szFileName;
    int                         nLine;

    size_t                      nDataSize;
    int                         nBlockUse;

    long                        lRequest;
    unsigned char               gap[4]; //nNoMansLandSize
    /* followed by:
    *  unsigned char           data[nDataSize];
    *  unsigned char           anotherGap[nNoMansLandSize];
    */
} _CrtMemBlockHeader1;


void * operator new(size_t size);
void  operator delete(void *p);

void * operator new[](size_t size);
void  operator delete[](void *p);

int _tmain(int argc, _TCHAR* argv[])
{
    int *k = new int;

    char *str = new char[100];

    *k = 10;

    strcpy(str, "Hi pipl!!!");

    delete k;
    delete [] str;

    return 0;
}


void * operator new(size_t size)
{
    return malloc(size);
}

void * operator new[](size_t size)
{
    return malloc(size);
}


void operator delete(void *p)
{
    _CrtMemBlockHeader1 *pHead = (((_CrtMemBlockHeader1 *)p)-1);
    size_t x = (((_CrtMemBlockHeader1 *)p)-1)->nDataSize;

    free(p);
}

void operator delete[](void *p)
{
    _CrtMemBlockHeader1 *pHead = (((_CrtMemBlockHeader1 *)p)-1);
    size_t x = (((_CrtMemBlockHeader1 *)p)-1)->nDataSize;
    free(p);
}


x - количество байтов освобождаемых.

2) Вопрос на засыпку:
Если вызвать delete от недействительного указателя, память испортится ???? - Испортится и память и прога, теоретически вплоть до форматирования винта.
324
17 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by Alexandoros
1) А как я в delete узнаю, скока я байт освобождаю, если передаётся в него токо указатель?



Память выделяется и освобождается блоками (страницми, в Win32 по 64 К), если одновременно будет освобождается более одного блока, то освободится только последний.

2.4K
17 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
Память выделяется и освобождается блоками (страницми, в Win32 по 64 К), если одновременно будет освобождается более одного блока, то освободится только последний.



Откуда такие сведения?

324
17 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by dinasok51
Откуда такие сведения?



Со школьной скамьи :)

2.4K
17 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by AndreySar
Со школьной скамьи :)



Может номер школы назовешь, а заодно и ссылку приведешь на указание подобных проблем в многопоточной среде?

1.0K
17 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by Alexandoros
В дебуг режиме -

Код:
typedef struct _CrtMemBlockHeader1
{
    struct _CrtMemBlockHeader1 * pBlockHeaderNext;
    struct _CrtMemBlockHeader1 * pBlockHeaderPrev;
    char *                      szFileName;
    int                         nLine;

    size_t                      nDataSize;
    int                         nBlockUse;

    long                        lRequest;
    unsigned char               gap[4]; //nNoMansLandSize

} _CrtMemBlockHeader1;


void operator delete[](void *p)
{
    _CrtMemBlockHeader1 *pHead = (((_CrtMemBlockHeader1 *)p)-1);
    size_t x = (((_CrtMemBlockHeader1 *)p)-1)->nDataSize;
    free(p);
}


x - количество байтов освобождаемых.


Вопрос: а по nBlockUse можно узнать, был ли уже освобождён данный блок, тоесть можно ли для него вызвать free.

351
18 февраля 2006 года
PitxBull
633 / / 22.12.2004
Цитата:
Originally posted by PitxBull
фрагментация памяти :

допустим допустимый размер кучи - 100 байт. И эти 100 байт распределены следующим образом:

00 - 29 Свободно ( 30 байт )
30 - 79 Занято ( 50 байт )
80 - 99 Свободно ( 20 байт )

Таким образом имеем ситуацию : утечек памяти нет, свободной памяти - 50 байт, но выделить программа может только 20 или 30 байт. Поэтому если запрашиваем 40 байт нас посылают....


Я доступно излагаю ? (c)

534
18 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by Alexandoros

Вопрос на засыпку:
Если вызвать delete от недействительного указателя, память испортится ???? - Испортится и память и прога, теоретически вплоть до форматирования винта.



По идее, при попытке освободить неверный блок должен вылететь эксэпшн. Но вылететь он может и не сразу, а при выходе из программы (когда MFC проводит дамп выделенной/освобождённой памяти). Для проверки целостности Heap'а можно использовать HeapValidate()

398
18 февраля 2006 года
Alexandoros
630 / / 21.10.2005
Короче фигня это все, я не верю что дизель забивает всю доступную память. И вероятность фрагментации тоже очень низкая. Скорее всего юзается невыделеный указатель, или, еще вероятнее, он удаляет объект, который потом опять юзается через указатель.
2.4K
18 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Alexandoros
... еще вероятнее, он удаляет объект, который потом опять юзается через указатель.



Скорее всего так оно и есть, тк программа перестает вываливаться когда diesel_den выкидывает delete.

Но наши гадания будут продолжаться еще долго, если автор с упорством, достйным лучшего применения, будет и дальше сам искать ошибку в new() и весь форум направлять в это русло

351
18 февраля 2006 года
PitxBull
633 / / 22.12.2004
Цитата:
Originally posted by Alexandoros
Короче фигня это все, я не верю что дизель забивает всю доступную память. И вероятность фрагментации тоже очень низкая. Скорее всего юзается невыделеный указатель, или, еще вероятнее, он удаляет объект, который потом опять юзается через указатель.


Так как программа работает сутками и при этом интенсивно использует выделение\освобождение памяти небольшими кусками то вероятность фрагментации не такая уж и низкая. У меня и не такое бывало. И потом что ему стоит проверить перед вызом new в котором кидается exception проверить максимальный размер блока и таким образом подтвердить или отвергнуть мое предположение.

324
18 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by PitxBull
Так как программа работает сутками и при этом интенсивно использует выделение\освобождение памяти небольшими кусками то вероятность фрагментации не такая уж и низкая. У меня и не такое бывало. И потом что ему стоит проверить перед вызом new в котором кидается exception проверить максимальный размер блока и таким образом подтвердить или отвергнуть мое предположение.



Лучше всего выделить всю необходимую память при загрузке программы и освободить при закрытии.
Вызывай _heapmin каждый раз, когда программа выделяет блоки размера, привышающего предел возможного для кучи малых блоков (по умолчанию 480 байт), так как блоками меньшего размера управляет сама CRT.
Также может возникнуть проблема при вызове HeapFree, если передать ей указатель на малый блок, полученный от new, т.к. new при выделении пямяти не использовал память кучи и не вызывал HeapAlloc.

1.0K
19 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by PitxBull
Я доступно излагаю ? (c)


доступно, я вас понял. вот только Alexandoros правильно говорит - фрагментация памяти, либо её нехватка в данном случае не может являться причиной глюков.
А выложить исходники я очень боюсь - это собственность фирмы, в которой я работаю :(

398
19 февраля 2006 года
Alexandoros
630 / / 21.10.2005
Цитата:

Также может возникнуть проблема при вызове HeapFree, если передать ей указатель на малый блок, полученный от new, т.к. new при выделении пямяти не использовал память кучи и не вызывал HeapAlloc.



new юзает HeapAlloc.


diesel_den если ты на 100% уверен, что глюк идет именно от нью, а не от юзанья невалидного блока - то зделай еще проще.Перед всеми нью поставь инкремент счетчика, а после делета - декремент, тогда точно будеш знать сколько байт выделено в даный момент.

Но повторю - твоя прога вылетает из-за того, что один поток юзает указатель, который уже грохнул другой поток.

2.4K
19 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by Alexandoros
new юзает HeapAlloc.


diesel_den если ты на 100% уверен, что глюк идет именно от нью, а не от юзанья невалидного блока - то зделай еще проще.Перед всеми нью поставь инкремент счетчика, а после делета - декремент, тогда точно будеш знать сколько байт выделено в даный момент.

Но повторю - твоя прога вылетает из-за того, что один поток юзает указатель, который уже грохнул другой поток.




disel_den Заключи всю свою прогр. в try - catch( ... ) затем распечатай что покажут в саtch GetLastError() GetExceptionCode() и сразу увидишь оператор на кот. программа вываливается

351
20 февраля 2006 года
PitxBull
633 / / 22.12.2004
Цитата:
Originally posted by diesel_den
доступно, я вас понял. вот только Alexandoros правильно говорит - фрагментация памяти, либо её нехватка в данном случае не может являться причиной глюков.
А выложить исходники я очень боюсь - это собственность фирмы, в которой я работаю :(


Да я не прошу тебя выкладывать здесь исходники. Просто перед первым new который кидает exception поставь функцию HeapCommit ( назначение которой посмотри в MSDN ) и проверь максимально доступный размер куска памяти и таким образом явно подтверди или опровергни мое предположение. Впрочем делать нефиг, счас пороюсь в исходниках посмотрю в каких случаях может в принципе выбрасывасться исключение.

351
20 февраля 2006 года
PitxBull
633 / / 22.12.2004
// bad_alloc.cpp
// compile with: /EHsc
#include<new>
#include<iostream>
using namespace std;

int main( )
{
char* ptr;
try
{
ptr = new char[~size_t(0)/2];
delete[ ] ptr;
}
catch( bad_alloc &ba)
{
cout << ba.what( ) << endl;
};
}

вот нашел в MSDN попробуй аналогично задействовать метод what класса bad_alloc что бы узнать причину exception.
351
20 февраля 2006 года
PitxBull
633 / / 22.12.2004
короче получается что в стандартном случае ( #define WINHEAP ) могут быть только две причины отказа выдления памяти. см. коды ошибок к функции HeapAlloc так как в случае #define WINHEAP оператор new через функцию malloc вызывает HeapAlloc, и если HeapAlloc возвращает NULL то new кидает bad_alloc exception. Причина 1 : нету памяти. Причина 2 : повреждение заговолвка кучи, то есть выход за пределы отведенной тебе ( конкретным new ) памяти.
1.0K
20 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by Alexandoros
Но повторю - твоя прога вылетает из-за того, что один поток юзает указатель, который уже грохнул другой поток.


Абсолютно с вами согласен, вот только не могу найти эту ошибку

2.4K
20 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by diesel_den
Абсолютно с вами согласен, вот только не могу найти эту ошибку


В 3-й раз
Заключи всю свою прогр. в try - catch( ... ) затем распечатай что покажут в саtch GetLastError() GetExceptionCode() и сразу увидишь оператор на кот. программа вываливается

1.0K
21 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by dinasok51
В 3-й раз
Заключи всю свою прогр. в try - catch( ... ) затем распечатай что покажут в саtch GetLastError() GetExceptionCode() и сразу увидишь оператор на кот. программа вываливается


А я в очередной раз повторяю, что у меня все операции уже давно заключены в try/catch, прога вываливается каждый раз в произвольном месте. Единственное, что обьеденяет эти сбои - их причина - нарушение кучи.

2.4K
21 февраля 2006 года
dinasok51
219 / / 12.11.2005
Цитата:
Originally posted by diesel_den
А я в очередной раз повторяю, что у меня все операции уже давно заключены в try/catch, прога вываливается каждый раз в произвольном месте. Единственное, что обьеденяет эти сбои - их причина - нарушение кучи.



Не поленюсь и в 4-й(уже почти интересно)

нужно закинуть в try/catch ВСЮ программу а не отдельные new и delete. И кажд поток должен быть заключен в свой try/catch. Только не говори что catch( ... ) не выловит Exception.

А с кучей и тебя все в порядке

398
21 февраля 2006 года
Alexandoros
630 / / 21.10.2005
Создай объект (Ferma), который будет держать в себе все объекты, которые ты выделяеш в куче. Доступ к определенному объекту пусть идет через индекс. Например

 
Код:
...
dynamic_cast<CClass2 *>(Ferma.GetObj(13))->DoSomething();

...
Ferma.DeleteObj(34); // здесь проверяй удален уже объект или нет. Если указатель в нуле - значит удален.

...
int index = Ferma.CreateObj(ObjType);


Панятна??? Работай, и не пость воды сюда больше :D
534
21 февраля 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by diesel_den
А я в очередной раз повторяю, что у меня все операции уже давно заключены в try/catch, прога вываливается каждый раз в произвольном месте. Единственное, что обьеденяет эти сбои - их причина - нарушение кучи.


Элементарный пример: компилируем

 
Код:
1.
    char * p = new char[12];
    delete[] (char *)(p+2);
2.
    char * p = new char[12];
    delete[] p;
    delete[] p;

Смотрим результат и делаем выводы. Фрагментация тут тоже не причём, если эксепшн говорит об Access Violation. Да элементарно ты считай количество выделенных/удалённых объектов + выделенной/освобождённой памяти. Если всё ровно, значит жук - использование уже удалённого указателя. Обнуляй ты все указатели после удаления, ёпрст!!! Уже неделю все только и делают, что обсуждают твой new, а ты всё ошибку найти не можешь... Да с таким количеством разных советов можно было уже свой оператор написать: тут и делать уже не надо ничего - копируй посты да вставляй в прогу :) Сделай уже ты нормально эти злементарные вещи и перестань наконец людей мучать
1.0K
27 февраля 2006 года
diesel_den
169 / / 22.12.2005
int* p = (int*)new char[4];
как правильно удалить?
delete[] p;
или
delete[] (char*)p;
То, что delete p; - не годиться, это я понимаю.
351
27 февраля 2006 года
PitxBull
633 / / 22.12.2004
Цитата:
Originally posted by diesel_den
int* p = (int*)new char[4];
как правильно удалить?
delete[] p;
или
delete[] (char*)p;
То, что delete p; - не годиться, это я понимаю.


мда... похоже на весеннее обострение.... на почве нехватки витаминов..... ты пробовал поговорить об этом со своим психиатром ?

1.0K
27 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by PitxBull
мда... похоже на весеннее обострение.... на почве нехватки витаминов..... ты пробовал поговорить об этом со своим психиатром ?


А слабо не выпендриваться и ответить по-существу?
Или Вы давно о таких тонких нюансах не думали?

324
27 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by diesel_den
int* p = (int*)new char[4];
как правильно удалить?
delete[] p;
или
delete[] (char*)p;
То, что delete p; - не годиться, это я понимаю.



А зачем тебе так надо написать? Неужели нельзя по-другому?

ну, а если так, то delete[] p;

1.0K
27 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by AndreySar
А зачем тебе так надо написать? Неужели нельзя по-другому?

ну, а если так, то delete[] p;



Конечно я не собираюсь так писать. Но в моей проге есть похожий код. Есть структура, последнее поле которой должно иметь переменную длину. Вот и выделяю я под экземпляр этой структуры память операцией new char[нужная длина], привожу полученный указатель к типу "указатель на мою структуру" и далее через этот указатель работаю с экземпляром этой структуры.

324
28 февраля 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by diesel_den
Конечно я не собираюсь так писать. Но в моей проге есть похожий код. Есть структура, последнее поле которой должно иметь переменную длину. Вот и выделяю я под экземпляр этой структуры память операцией new char[нужная длина], привожу полученный указатель к типу "указатель на мою структуру" и далее через этот указатель работаю с экземпляром этой структуры.



 
Код:
struct MyStruct
{
    ...
    char *str;
};

MyStruct.str = new char[80];
...
delete[] MyStruct.str;


Я правильно тебя понял?
1.0K
28 февраля 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by AndreySar
 
Код:
struct MyStruct
{
    ...
    char *str;
};

MyStruct.str = new char[80];
...
delete[] MyStruct.str;


Я правильно тебя понял?



нет

3
28 февраля 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by diesel_den
нет


Видимо, такая конструкция:

 
Код:
struct A
{
   ......
   type arr[1];
};

A* pA = (A*)new char[sizeof(A) + (n-1)*sizeof(type)];

Только вот это не очень хороший стиль программирования.
Единственное применение, которое я могу представить, это передача некоторому железу (в т.ч. в сеть), но и это можно решить иначе.
324
01 марта 2006 года
AndreySar
532 / / 01.08.2004
Цитата:
Originally posted by Green
Видимо, такая конструкция:
 
Код:
struct A
{
   ......
   type arr[1];
};

A* pA = (A*)new char[sizeof(A) + (n-1)*sizeof(type)];

Только вот это не очень хороший стиль программирования.
Единственное применение, которое я могу представить, это передача некоторому железу (в т.ч. в сеть), но и это можно решить иначе.



Зачем гадать, может он сам предоставит пример?

1.0K
01 марта 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by AndreySar
Зачем гадать, может он сам предоставит пример?


Ну в общем Green написал всё верно. И применение он написал близкое к моему, так как в своей системе я пытаюсь наладить обмен "пакетами" переменной длины, как бы свой протокол.

534
01 марта 2006 года
HarryAxe
448 / / 19.01.2006
Цитата:
Originally posted by diesel_den
Ну в общем Green написал всё верно. И применение он написал близкое к моему, так как в своей системе я пытаюсь наладить обмен "пакетами" переменной длины, как бы свой протокол.

А почему не используешь вариант, описанный AndreySar? Если уж юзаешь new/delete, почему бы деструктор не написать для структуры, и тогда не возникало бы никакой неопределённости, связанной с правильностью удаления

1.0K
01 марта 2006 года
diesel_den
169 / / 22.12.2005
Цитата:
Originally posted by HarryAxe
А почему не используешь вариант, описанный AndreySar? Если уж юзаешь new/delete, почему бы деструктор не написать для структуры, и тогда не возникало бы никакой неопределённости, связанной с правильностью удаления



прикол в том, что байт может прийти меньше, чем сумма размеров статических полей структуры. в моём случае некоторым модулям системы не нужны последние поля (причём у разных модулей кол-во нужных от начала полей разное). и я не хочу делить операцию пересылки пакета на две части (пересылка постоянной составляющей и пересылка составляющей переменной длины), так как это просто неудобно, а я стараюсь написать "эллегантный" код.

3
02 марта 2006 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by diesel_den
а я стараюсь написать "эллегантный" код.


Использование переменной длины - это совсем не "элегантный код". Лучше сделай классы без всяких переменных длин, с обычными агрегациями и методами сериализации.

100.0M
04 ноября
morozilka
0 / / 04.11.2019
всегда хотел в этом разобраться,спасибо за помощь

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог