Является ли хорошей практикой использование вызова функции внутри функции? - PullRequest
1 голос
/ 01 мая 2019

У меня очень большая C-программа для молекулярной динамики.Он работает правильно с N = 10000 частиц.Когда я увеличивал частицы до N = 100000 путем увеличения размера переменной, это вызывало ошибку сегментации.

Я выполнил ulimit -s unlimited, и проблема была решена.

Q1. Любой способ проверить, сколько стековой памяти будет использовать мой код, проверка производительности кода (оптимизация), утечка памяти.

Q2. Если структура моего кода похожа на вложенные функции,

int main() {
    function1();
    return 0;
}

void function1() {
    for(int i=0;i<1000;i++) {
        function2();
    }
}

void function2() { 
    double Var[100000];
}

Будет ли использование function2() внутри цикла for использовать больше памяти стекачем выполнить его только один раз?

Ответы [ 3 ]

3 голосов
/ 01 мая 2019

Q1.Я хочу знать, есть ли способ проверить, сколько стековой памяти будет использовать мой код, проверка производительности кода (оптимизация), утечка памяти.

Не совсем.Стандарт C даже не упоминает стек, и любой компилятор C может создавать двоичные файлы, которые не используют стек и все еще соответствуют стандарту C.

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

Производительность не следует прогнозировать.Его следует измерить, а затем оптимизировать при необходимости.

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

Q2.если структура моего кода похожа на вложенные функции, то из-за вызова function2 внутри цикла for он будет использовать больше стековой памяти, чем один раз?

Нет.Каждый раз, когда вызывается function2(), создается новый кадр стека с достаточным пространством для 100000 удвоений.Но он будет освобожден сразу же, когда функция вернется.Проблема здесь не в том, чтобы вызывать функцию в цикле.Проблема в том, что вы размещаете ОГРОМНЫЕ массивы в стеке, что может стать проблемой.Вам следует рассмотреть возможность их динамического распределения.По сути, это будет выглядеть так:

void function2
{
    double *var = malloc(100000*sizeof(*var));
    /* Code */
    free(var);
}

Если вы используете рекурсивные функции, стек может стать проблемой.Давайте рассмотрим эту функцию суммы, которая суммирует все натуральные числа вплоть до num:

unsigned long long sum(unsigned long long num)
{
    if(num == 0) return num;
    return num + sum(n-1);
}

A long long обычно составляет 8 байтов, поэтому, если вы используете эту функцию для очень большого числа (возможно, 100000 или 1000000), вы можетевозникают проблемы со стеком.

2 голосов
/ 01 мая 2019

Q1 . Я хочу знать, есть ли способ проверить, сколько стековой памяти будет использовать мой код, проверка производительности кода (оптимизация), утечка памяти.

Возможно, вы сможете оценить, сколько стекового пространства потребуется вашей программе, проанализировав граф вызовов и переменные, объявленные в каждой функции, но это не так просто для сложной программы. Гораздо сложнее, если речь идет о какой-либо рекурсии, но, по крайней мере, нужно уметь установить грубую верхнюю границу. Но самый простой способ - измерить использование при работе с характеристическими входами.

Абсолютная производительность - , чрезвычайно , которую трудно предсказать людям. Лучшее, что мы обычно можем сделать надежно, - это определить, как производительность будет зависеть от размера проблемы. Сравнительная производительность всегда должна измеряться.

Что касается утечки памяти, тщательный анализ кода людьми обычно может обнаружить утечки памяти, но разумно дополнить это с помощью инструмента анализа использования памяти во время выполнения, такого как Valgrind. Такие инструменты обнаруживают утечки даже в хорошо проанализированном коде с частотой ударов.

Q2 . если структура моего кода похожа, вложенные функции, [...] из-за вызова function2 внутри цикла он будет использовать больше стековой памяти, чем при использовании только один раз?

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

Однако, когда функция рекурсивно вызывает себя прямо или косвенно, она, вероятно, использует дополнительные ресурсы, пропорциональные глубине рекурсии. Я говорю «вероятно», потому что в некоторых случаях компилятор может преобразовать рекурсию в итерацию в рамках одного вызова функции.

0 голосов
/ 01 мая 2019

Лучше не создавать большие объекты в стеке. Вместо этого они должны выделяться динамически с malloc в C или new в C ++.

После этого ваша программа может восстановиться, если программа отклонит запрос на выделение.

Используя новые интеллектуальные указатели в C ++, вы можете обеспечить освобождение всех выделений и отсутствие утечек, в противном случае вам просто нужно «тщательно написать свой код», что является недостатком программирования на C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...