Приостановка программы не меняется после вызова malloc в цикле?

Предполагается, что запуск этого фрагмента кода приведет к увеличению перерыва в программе примерно на malloc_counts * _SC_PAGESIZE, вместо этого я каждый раз получаю фиксированный перерыв в программе, так почему это так. Предполагается, что malloc вызывает brk или sbrk, которые сами округляют размер, передаваемый на следующую страницу (с некоторой дополнительной работой). Так что же происходит?

#include <stdio.h>
#include <malloc.h>
#include <unistd.h>

int main(){
    const long malloc_counts = 10;
    printf("PAGE SIZE: %ld\n", sysconf(_SC_PAGESIZE));
    void* allocated_pool[malloc_counts];
    for(int counter=0; counter < malloc_counts; counter++)
    {
        printf("program brk: %p\n",sbrk(0));
        allocated_pool[counter] = malloc(127*4096);
    }
}

person Khaled    schedule 14.09.2020    source источник
comment
counter <= malloc_counts; вызовет переполнение массива, когдаcounter == malloc_counts;   -  person Weather Vane    schedule 14.09.2020
comment
Linux malloc может использовать либо sbrk, либо mmap для захвата памяти, и последний не изменит точку останова. Я не знаю, как текущий алгоритм решает, что использовать. Вы можете использовать strace, чтобы увидеть, что делается.   -  person Nate Eldredge    schedule 14.09.2020
comment
Условие цикла counter <= malloc_counts должно использовать оператор сравнения «меньше-тогда» вместо «меньше-или-равно».   -  person CiaPan    schedule 14.09.2020
comment
@CiaPanI исправил эту опечатку сейчас.   -  person Khaled    schedule 14.09.2020
comment
Попробуйте с экс. malloc(127 * 4096);   -  person KamilCuk    schedule 14.09.2020
comment
@KamilCuk То же самое Ничего не меняется   -  person Khaled    schedule 14.09.2020
comment
Такой же? Действительно? Изменения для меня. Какую версию стандартной библиотеки вы используете? Пожалуйста, если можно, сделайте код полностью компилируемым исходным кодом - угадывать #include и добавлять int main() неинтересно. Что возвращает mallinfo в каждом цикле? malloc_stats? mallopt с M_MMAP_THRESHOLD тоже было бы интересно. не удается воспроизвести, ссылка на godbolt Каково значение malloc_counts?   -  person KamilCuk    schedule 14.09.2020
comment
@kamilCuk glibc 2.31 , но даже если это сработало для вас, 127 * 4096 - это очень большая сумма, намного превышающая размер страницы Linux (необходимо более одной страницы), что еще больше сбивает с толку, поскольку не похоже, что отличается от мне .   -  person Khaled    schedule 14.09.2020
comment
@kamilCuk Теперь я добавил весь исходный код   -  person Khaled    schedule 14.09.2020
comment
Как вы компилируете код? Вы компилируете с оптимизацией? Какой линукс вы используете? Моя текущая ставка состоит в том, что вы компилируете с включенной оптимизацией... если нет, пожалуйста, опубликуйте статистику malloc по пути и значение M_MMAP_THRESHOLD.   -  person KamilCuk    schedule 14.09.2020
comment
@KamilCuk Я запускаю Ubuntu20 и компилирую с использованием значений по умолчанию Clion (которые, я думаю, конечно, используют оптимизацию). Можете ли вы сказать мне, что получится, если вы сделаете размер malloc таким же, как размер страницы, может быть, даже немного больше.   -  person Khaled    schedule 14.09.2020
comment
@KamilCuk только что попытался вручную скомпилировать, используя gcc prog.c все еще безрезультатно.   -  person Khaled    schedule 14.09.2020
comment
Попробуйте gcc -O0 prog.c, чтобы убедиться. Если нет, как сказано, запросите информацию о malloc и запросите M_MMAP_THRESHOLD и посмотрите, что происходит. Также проверьте сборку и убедитесь, что вызовы malloc действительно существуют и не оптимизированы.   -  person KamilCuk    schedule 14.09.2020
comment
Ах, 127*4096 это слишком! к 127*1024, мой плохой. По умолчанию M_MMAP_THRESHOLD это 128*1024   -  person KamilCuk    schedule 14.09.2020


Ответы (1)


что я думаю, конечно, используя оптимизацию

Ваш компилятор оптимизирует вызовы malloc out, поскольку они не используются. Поскольку вызовы malloc удаляются, ничего не меняется и куча не перемещается.

И glibc сильно перераспределяет ресурсы, поэтому значение должно быть достаточно большим, чтобы оно его увидело. И по умолчанию M_MMAP_THRESHOLD кажется 128 * 1024 . Таким образом, вы должны выбрать достаточно большое значение, но ниже порога mmap, чтобы увидеть разницу в glibc.

Отключите оптимизацию вашего компилятора и выделите много, и куча будет перемещена. Попробуйте следующее:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
    printf("PAGE SIZE: %ld\n", sysconf(_SC_PAGESIZE));
    #define malloc_counts  20
    void *allocated_pool[malloc_counts];
    for(int counter = 0; counter < malloc_counts; counter++) {
        printf("program brk: %p\n", sbrk(0));
        allocated_pool[counter] = malloc((size_t)127 * 1024);
        *(void *volatile *)&allocated_pool[counter];
    }
}
person KamilCuk    schedule 14.09.2020
comment
M_MMAP_THRESHOLD это -3, что я еще не знаю, что это значит - person Khaled; 14.09.2020
comment
malloc, похоже, в порядке, и при вызове (не оптимизированном) обнаружил эту строку ``` callq 10e0 ‹malloc@plt› ``` , так что эта проблема только со мной, я имею в виду, что приведенный выше код в вопросе работает для ты нормально. - person Khaled; 14.09.2020