Перейти к содержанию
    

А мне хочется и другой вариант попробовать, складывать команды в очередь пока есть свободная память, а потом, те что не влезают, выкидывать.
У меня в таком случае в перегруженном operator new() из очереди удаляются самые старые события (которые, наверняка, уже мало кому интересны) и после каждого удаления производится повторная попытка выделить память для нового события. Если очередь уже пуста, а памяти все еще не хватает - то, значит, что-то уже сильно порушено и остается только перезагружаться.

 

С обычным new это невозможно.
А с operator new ( std::size_t count, const std::nothrow_t& tag) - возможно. В этом случае компилятор вставляет проверку возвращенного new(std::nothrow) указателя и вызывает конструктор только в том случае, если new вернул не 0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня в таком случае в перегруженном operator new() из очереди удаляются самые старые события (которые, наверняка, уже мало кому интересны) и после каждого удаления производится повторная попытка выделить память для нового события. Если очередь уже пуста, а памяти все еще не хватает - то, значит, что-то уже сильно порушено и остается только перезагружаться.

Такой подход требует реализации собственного, аля, сборщика мусора.

 

А с operator new ( std::size_t count, const std::nothrow_t& tag) - возможно. В этом случае компилятор вставляет проверку возвращенного new(std::nothrow) указателя и вызывает конструктор только в том случае, если new вернул не 0.

Почти так и сделал. С std::nothrow сделать не получилось. Сделал проще, operator new(size_t,void*). Кстати, компилятор никаких проверок не вставляет, конструктор вызывается в любом случае. Вставил проверку перед вызовом new.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почти так и сделал. С std::nothrow сделать не получилось. Сделал проще, operator new(size_t,void*).
Проще? Покажите, сравним. Это так по-русски - чуть что, придумывать свой велосипед. Причем почти всегда с квадратными колесами.

 

Кстати, компилятор никаких проверок не вставляет, конструктор вызывается в любом случае.
У меня вставляет, что я делаю неправильно?

#include    <new>

class a
{
public:
    a();
};

a * pA;

void test()
{
    pA = new(std::nothrow) a;

}

  18:main.cpp      **** void test()
  19:main.cpp      **** {
100                      .loc 1 19 0
101                      .cfi_startproc
102                      @ args = 0, pretend = 0, frame = 0
103                      @ frame_needed = 0, uses_anonymous_args = 0
104 0000 10B5             push    {r4, lr}    @
105                  .LCFI0:
106                      .cfi_def_cfa_offset 8
107                      .cfi_offset 4, -8
108                      .cfi_offset 14, -4
  20:main.cpp      ****     pA = new(std::nothrow) a;
109                      .loc 1 20 0
110 0002 0549             ldr    r1, .L7    @,
111 0004 0120             movs    r0, #1    @,
112 0006 FFF7FEFF         bl    _ZnwjRKSt9nothrow_t    @  <-------- new(std::nothrow)
113                  .LVL0:
114 000a 0446             mov    r4, r0    @ D.8513,
115 000c 08B1             cbz    r0, .L2    @,                  <------- проверка
116                      .loc 1 20 0 is_stmt 0 discriminator 1
117 000e FFF7FEFF         bl    _ZN1aC1Ev    @           <------- вызов конструктора
118                  .LVL1:
119                  .L2:
120                      .loc 1 20 0 discriminator 4
121 0012 024B             ldr    r3, .L7+4    @ tmp112,
122 0014 1C60             str    r4, [r3]    @ D.8513, pA
123 0016 10BD             pop    {r4, pc}    @

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кусочек кода и конструктор

int main(void)
{
  EngineTask = new TEngineTask() ;
......

 

...........
class TEngineTask : public TTask
{
 public:
    TEngineTask ()
     {
        NOP();
        active = false ;
        NOP();
     }
.........

 

 

ВАЖЕН атрибут которым оператор new помечен:

 

inline void* operator new(size_t size)

398       	__libc_init_array() ;
0800a82a:   bl 0x800aec0 <__libc_init_array>
0800a82e:   movs r0, #12                           <-------- выхов main()
0800a830:   bl 0x800a394 <malloc(size_t)>          <-------- EngineTask = new TEngineTask() ;
0800a834:   movs r5, #0                            <-------- вызов конструктора
0800a836:   ldr r3, [pc, #248]      ; (0x800a930 <ResetHandler()+744>)
0800a838:   str r3, [r0, #0]
0800a83a:   str r5, [r0, #4]
0800a83c:   nop 
14                 active = false ;
0800a83e:   strb r5, [r0, #8]
15                 NOP();
0800a840:   nop 
0800a842:   ldr r3, [pc, #240]      ; (0x800a934 <ResetHandler()+748>)

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

 

 

inline void* operator new(size_t size) _GLIBCXX_NOEXCEPT

398       	__libc_init_array() ;
0800a82a:   bl 0x800aec4 <__libc_init_array>
0800a82e:   movs r0, #12                           <-------- выхов main()
0800a830:   bl 0x800a394 <malloc(size_t)>          <-------- EngineTask = new TEngineTask() ;
0800a834:   cbz r0, 0x800a844 <ResetHandler()+508> <-------- проверка того что вернул malloc
12              {
0800a836:   ldr r2, [pc, #252]      ; (0x800a934 <ResetHandler()+748>)  <- вызов конструктора
0800a83a:   stmia.w r0, {r2, r3}
13                 NOP();
0800a83e:   nop 
14                 active = false ;
0800a840:   strb r3, [r0, #8]
15                 NOP();
0800a842:   nop 
0800a844:   ldr r3, [pc, #240]      ; (0x800a938 <ResetHandler()+752>)

компилятор полагает что new не генерит эксепшенов и поэтому нужно проверить результат malloc чтоб не улететь в космом

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

EngineTask = new TEngineTask();

pA = new(std::nothrow) a;

Найдите десять отличий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Найдите десять отличий.

Насколько я понял, klen привёл третий вариант, в котором

void* operator new(size_t size)

объявлен как noexcept. В этом случае компилятор тоже вставляет проверку результата выделения памяти перед вызовом конструктора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проще? Покажите, сравним. Это так по-русски - чуть что, придумывать свой велосипед. Причем почти всегда с квадратными колесами.

Согласен, с "проще" я несколько погорячился :)

Просто с обычным new(std::nothrow) у меня проект не собирается, зачем-то тащит библиотечную "кучу" и что-то про исключения.

 

Вот мой код.

                
void* __mem = malloc(sizeof(Packet));
if (__mem == nullptr)
{
        ...
}
else
{
    packet = new(__mem) Packet(...);
        ...

 

переопределение new

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я понял, klen привёл третий вариант, в котором void* operator new(size_t size) объявлен как noexcept. В этом случае компилятор тоже вставляет проверку результата выделения памяти перед вызовом конструктора.
Но это же велосипед. Уже существующий new(std::nothrow_t) делает ровно то же самое, всегда есть в заголовочном файле <new> любого компилятора и к нему там всегда приписан нужный правильный атрибут. Используя его не нужно думать, _GLIBСXX или какой еще _NOEXCEPT туда надо дописывать (хватает, кстати, обычного переносимого throw() ). Каюсь, тоже использовал такое переопределение, хоть это и грязный хак. Знакомый со стандартом программист, глядя в такой исходник и не зная о переопределении, вправе ожидать совершенно другого поведения кода. Это примерно равносильно #define true false, поэтому советовать такое кому-то еще я никогда не буду.

 

Просто с обычным new(std::nothrow) у меня проект не собирается, зачем-то тащит библиотечную "кучу" и что-то про исключения.
Странно. Для new() ему нужен malloc(), для delete() - free(), если эти две функции определены в проекте - у меня ничего не тащит. Можете сделать и выложить простейший проект?

переопределение new
Велосипед, такой велосипед ;)

If placement_params are provided, they are passed to the allocation function as additional arguments. Such allocation functions are known as "placement new", after the standard allocation function void* operator new(std::size_t, void*), which simply returns its second argument unchanged. This is used to construct objects in allocated storage:

 

Кстати, чтобы не писать (void)size; вы можете опустить имя первого параметра в определении функции:

void* operator new(size_t, void* p)
{
    return p;
}

 

 

И попробуйте все же победить, ваш код станет еще проще:

                
packet = new(std::nothrow) Packet;
if (packet == nullptr)
{
        ...
}
else
{
        ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но это же велосипед. Уже существующий new(std::nothrow_t) делает ровно то же самое, всегда есть в заголовочном файле <new> любого компилятора и к нему там всегда приписан нужный правильный . Знакомый со стандартом программист, глядя в такой исходник и не зная о переопределении, вправе ожидать совершенно другого поведения кода. Это примерно равносильно #define true false, поэтому советовать такое кому-то еще я никогда не буду.

я с Вами полностью согласен - нужно правильно уметь использовать стандарт. если он позволяет сделать что то - то делать именно его инструментом а не велосипедом. но у меня следующие мысли, первое - переопределение сокращает запись - везде писать new(std::nothrow_t) вместо new.

второе более интересное. в принципе не сложно в своем коде писать new(std::nothrow_t) - это даже правильно как Вы заметили. нам повезло с STL - разработчтки контейнеров и прочего добра требующих динамического распределения памяти грамотно не стали пользоваться операторами new и delete - вместо этого каждый класс требует специальный класс аллокатора - который мы уже тут в хидере определили как нам нужно. все вроде бы хорошо ... остается вопорос - а что если в проект чужая либа в исходниках компилится и линкуется? там прийдется все new переправлять на new(std::nothrow_t), поэтому велосипед пока актуален на мой взгляд.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

klen, как там с падением компилятора на исходниках с ключами под Cortex-A9? Нужна ли дополнительная информация для лечения бага?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

klen, как там с падением компилятора на исходниках с ключами под Cortex-A9? Нужна ли дополнительная информация для лечения бага?

еще не занимался, на работе жоппа, выходные ночевал на работе...я не забыл.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

релизная сборка 6.2.0

linux64:

http://klen.org/Files/DevTools/x86_64-kgp-....2.0_CORYLUS.7z

 

win64:

http://klen.org/Files/DevTools/x86_64-kgp-....2.0_CORYLUS.7z

 

2_Genadi Zawidowski

проверяйте! сборка под линух у меня пережевала Ваш фалик :) сборка под масдай под wine тоже

wine ./arm-kgp-eabi-gcc.exe -c -mcpu=cortex-a9 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -fno-math-errno -funroll-loops -fgraphite -ffunction-sections -fdata-sections -ffat-lto-objects -Ofast -flto -gdwarf-2 -fomit-frame-pointer -Wall -Wstrict-prototypes -DNDEBUG=1 -DCPUSTYLE_R7S721=1 -DCPUSTYLE_R7S721020=1 -I../ -I../rza1x_inc usbd.c -o usbd.o

объектники бинарно идентичны :)

должно взлететь!

Вы С++ используете? если да то используете ли исключения (try{} catch() )? если да то есть тонкие замечание пл кодогенерации.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С++ используете?

Не использую. Скачал, проверил - на компиляции для A9 не сыпется. Работоспособность пока неначем проверять.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не использую. Скачал, проверил - на компиляции для A9 не сыпется. Работоспособность пока неначем проверять.

для A9 по хорошему собрать отдельную сборку. у меня самого есть рабочая машинка на i.MX6Q.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Решил попробовать Вашу сборку под винду.

Не находит либу: libc_nano.a

 

Вы по идеологическим причинам их не собираете?

 

Так невозможно сравнить Вашу сборку со сборками с ланчпада...

 

А вообще проект компилируется нормально, но не собирается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...