Russian Qt Forum
Ноябрь 23, 2024, 21:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: Можно ли "заморозить" слот/сигнал?  (Прочитано 18425 раз)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #30 : Сентябрь 21, 2012, 23:03 »

Сейчас проверил на голых malloc и realloc - результат тот-же после 4х-5и итераций SIGSEGV.
Протрассировал исполнение:
Для выделения памяти используется системный вызов mmap2, для перевыделения mremap. Почему-то память ядром выделяется от больший адресов к меньшим, это и объясняет, почему каждый последующий вызов на 400 мб не влезает в оставшуюся дырку.

Цитировать
mmap2(NULL, 419434496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x84fd2000
mremap(0x84fd2000, 419434496, 4096, MREMAP_MAYMOVE) = 0x84fd2000
write(1, "after squeeze, press enter 1\n", 29after squeeze, press enter 1
) = 29
mmap2(NULL, 419434496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x6bfd1000
mremap(0x6bfd1000, 419434496, 4096, MREMAP_MAYMOVE) = 0x6bfd1000
write(1, "after squeeze, press enter 2\n", 29after squeeze, press enter 2
) = 29
mmap2(NULL, 419434496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x52fd0000
mremap(0x52fd0000, 419434496, 4096, MREMAP_MAYMOVE) = 0x52fd0000
write(1, "after squeeze, press enter 3\n", 29after squeeze, press enter 3
) = 29
mmap2(NULL, 419434496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x39fcf000
mremap(0x39fcf000, 419434496, 4096, MREMAP_MAYMOVE) = 0x39fcf000
write(1, "after squeeze, press enter 4\n", 29after squeeze, press enter 4
) = 29
mmap2(NULL, 419434496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x20fce000
mremap(0x20fce000, 419434496, 4096, MREMAP_MAYMOVE) = 0x20fce000
write(1, "after squeeze, press enter 5\n", 29after squeeze, press enter 5
) = 29
mmap2(NULL, 419434496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

Так, что это не глюк Qt и даже не глюк malloc/realloc, это просто особенность выделения памяти ядром. Случай специфичный просто.
Записан

Гугль в помощь
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #31 : Сентябрь 22, 2012, 11:51 »

Не понимаю этих соображений насчет "дырок" - по-моему они давно стали историей, сейчас выделяется страницами и.т.д. (помню Вы сами отвечали на подобный вопрос).

Я столкнулся с этой проблемой лет 5 назад. Погуглив понял так что это не баг, такая реализация realloc допустима. Просто выкинул у себя все realloc заменив их на malloc + memmove, это работает везде. Спрашивал что на др платформах - хотя это уже "академический интерес". Вроде на Win7 все хорошо, а на каком-то др Вындоуз - то же самое. Когда вчера постил, мелькои проверил на OSX 10.7 - там все освобождается.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #32 : Сентябрь 22, 2012, 12:49 »

Может, чтобы не сталкиваться с этой проблемой, использовать один менеджер везде?
Тем более помнится Вам уже предлагали это сделать здесь.
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #33 : Сентябрь 22, 2012, 13:28 »

Может, чтобы не сталкиваться с этой проблемой, использовать один менеджер везде?
Тем более помнится Вам уже предлагали это сделать здесь.
Звучит типа "вот ведь какой бестолковый! Ему же предлагали.." Улыбающийся А как я это сделаю? Полезу менять исходники Qt и буду повторять процесс с каждой новой версией? Как-то не тянет

Просто такая подлянка с realloc есть и знать о ней не помешает. А если действительно большие данные (гигабайты) то все равно лучше свой контейнер, ни std, ни Qt контейнеры не устроят. Поэтому проблема не так уж актуальна. 
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #34 : Сентябрь 22, 2012, 14:15 »

А как я это сделаю? Полезу менять исходники Qt и буду повторять процесс с каждой новой версией? Как-то не тянет
Зачем что-то менять Непонимающий Достаточно просто "перегрузить" malloc/realloc/free на уровне библиотеки. Хотя бы через тот же LD_PRELOAD.
Записан

Qt 5.11/4.8.7 (X11/Win)
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #35 : Сентябрь 22, 2012, 19:33 »

Нет никакой подлянки, я же расписал. Всё работает четко и предсказуемо. Просто надо менять способ работы с памятью. Или писать свой менеджер памяти, который такому поведению не подвержен. Но в большинстве случаев всё хорошо.
Записан

Гугль в помощь
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #36 : Сентябрь 22, 2012, 20:08 »

Нет никакой подлянки, я же расписал. Всё работает четко и предсказуемо. Просто надо менять способ работы с памятью. Или писать свой менеджер памяти, который такому поведению не подвержен. Но в большинстве случаев всё хорошо.
Ну вот Вам очередной примерчик. Запускаю (OSX 10.6.8 ), консоль радостно выдает ошибку. Ставлю USE_REALLOC  0, т.е. обхожу realloc, использую вместо него malloc + memmove. Все работает. Уже и размер блока взял пионерские 10 Mb - ну как же я все время не попадаю на то самое большинство случаев где все хорошо?  Улыбающийся
Код
C++ (Qt)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define USE_REALLOC 1
 
void * ReAlloc( void * addr, size_t size )
{
if (!addr) return malloc(size);
 
#if USE_REALLOC
return realloc(addr, size);
#else
void * blk = malloc(size);
memmove(blk, addr, size);
free(addr);
return blk;
#endif
}
 
int main ()
{
const int count = 10 * (1024 * 1024);
 
int i;
for (i = 0; i < 1000; ++i) {
void * test = malloc(count);
// void * test = malloc(count - i * 1024);   // можно и так, результат тот же
 
if (test)
test = ReAlloc(test, 4);
if (!test) {
printf("can't alloc/realloc\n");
break;
}
}
 
printf("steps done %d\n", i);
 
return 0;
}
 
« Последнее редактирование: Сентябрь 23, 2012, 05:21 от Igors » Записан
DmitryM
Гость
« Ответ #37 : Сентябрь 22, 2012, 21:04 »

Так, что это не глюк Qt и даже не глюк malloc/realloc, это просто особенность выделения памяти ядром. Случай специфичный просто.
Вроде как в Linux с glibc malloc работает через brk.
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #38 : Сентябрь 22, 2012, 23:22 »

Ну вот Вам очередной примерчик. Запускаю (OSX 10.6.8 ), консоль радостно выдает ошибку. Ставлю USE_REALLOC  0, т.е. обхожу realloc, использую вместо него malloc + memmove. Все работает. Уже и размер блока взял пионерские 10 Mb - ну как же я все время не попадаю на то самое большинство случаев где все хорошо?  Улыбающийся

Вот диаграмма с двумя способами realloc, надеюсь, разница будет понятна:

Если рисунка не видно - залогиньтесь в гугле Крутой

Цитировать
Вроде как в Linux с glibc malloc работает через brk.
strace говорит о том, что память в линуксе выделяется с помощью mmap2. Что такое "brk" ?
« Последнее редактирование: Сентябрь 22, 2012, 23:28 от navrocky » Записан

Гугль в помощь
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #39 : Сентябрь 23, 2012, 05:36 »

Вот диаграмма с двумя способами realloc, надеюсь, разница будет понятна:
Если рисунка не видно - залогиньтесь в гугле Крутой
Рисунок видно, спасибо. Вопросы:

1) Oткуда взялось смелое предположение о непрерывном блоке? Страничный механизм уже не работает или как?

2) Хорошо, примем Вашу версию и будем распределять каждый новый блок меньше предыдущего (я добавил строчку в пример). Результат - отказ памяти, просто на неск шагов дальше. Как Вы это поясните?

3) Какая разница прикладной программе "почему" - факт налицо, с realloc получен отказ, заменив его - все норм. Зачем же отрицать что ф-ция проблемная и подлянка возможна? Объясняя "почему" Вы ведь тем самым признаете что факт имеет место  Улыбающийся

Кстати какой у Вас ОС? (для коллекции/статистики проблемы)
Спасибо
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #40 : Сентябрь 23, 2012, 10:26 »

Виртуальная память выделяется непрерывным блоками.

У меня opensuse 12.1.

Попробуйте ваш пример с декрементом размера блока >=4096. Размер страницы 4096 байт на интелях.
Записан

Гугль в помощь
DmitryM
Гость
« Ответ #41 : Сентябрь 23, 2012, 16:47 »

strace говорит о том, что память в линуксе выделяется с помощью mmap2. Что такое "brk" ?
man sbrk, а в man malloc
сказано
Цитировать
Normally, malloc() allocates memory from the heap, and adjusts the size of the heap as required, using sbrk(2). When allocating blocks of memory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation allocates the memory as a private anonymous mapping using mmap(2). MMAP_THRESHOLD is 128 kB by default, but is adjustable using mallopt(3). Allocations performed using mmap(2) are unaffected by the RLIMIT_DATA resource limit (see getrlimit(2)).

Нигде не сказано, что realloc должен каждый раз выделать новый блок памяти(это есть в C99), или освобождать память в случае уменьшения размера блока.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #42 : Сентябрь 23, 2012, 20:21 »

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

Когда-то пробовал разобраться (уже довольно давно) и понял так: для распределения большого блока вызывается vmalloc (OSX) который распределяет всегда целое число страниц и резервирует непрерывное дисковое пр-во. Мои попытки воспользоваться vmrealloc ни к чему не привели - уменьшить выделенный блок не удавалось, можно было только удалить. Пришел к выводу что некоторые ОС могут держать такие блоки и это место недоступно для др выделений из соображений непрерывности на диске.

Впрочем с точки зрения прикладной программы причина не так уж важна

 
Записан
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.146 секунд. Запросов: 23.