Память остается выделенной, когда поток C++ выходит?

Можете ли вы попробовать с ниже.

select * from(Select bn_ms_bm_bankmaster.CMP_CUSTCODE AS Id_client,BN_CS_MP_MASTERPROFILE.CMP_NAME as Nom_prenom,PR_GN_AD_ENTITYADDRESS.PMP_MUNCIPCODE FROM bn_ms_bm_bankmaster INNER JOIN BN_CS_MP_MASTERPROFILE ON bn_ms_bm_bankmaster.CMP_CUSTCODE=BN_CS_MP_MASTERPROFILE.CMP_CUSTCODEINNER JOIN PR_GN_AD_ENTITYADDRESS ON bn_ms_bm_bankmaster.CMP_CUSTCODE=PR_GN_AD_ENTITYADDRESS.CMP_CUSTCODE);
5
задан Community 23 May 2017 в 10:27
поделиться

8 ответов

Оказывается, проблема была вызвана неправильным использованием памяти, как и ожидалось. Я на 99% уверен, что следующий пример точен; это в значительной степени псевдокод, поэтому компиляция, очевидно, не будет.

Обновление:

Только что добавили 3-е решение благодаря nusi.

Неправильный путь (с памятью стека):

std::map<int, MyType1> myMap;

void firstFunctionRunFromThread1()
{
    MyType1 mt1;
    mt1.Test = "Test 1";
    myMap[0] = mt1;
}

void onlyFunctionRunFromThread2()
{
    MyType1 mt1 = myMap[0];

    // This actually does print "Test 1", so the memory is being accessed.
    std::cout << mt1.Test << endl;

    /* However, because we're using stack memory here, this value is lost
     * when we go back to thread #1. */
    mt1.Test = "Test 2";
}

void secondFunctionFromThread1()
{
    MyType1 mt1 = myMap[0];

    // This will actually print out "Test 1", where "Test 2" is expected!
    std::cout << mt1.Test << endl;
}

сложный , правильный метод (с использованием кучи памяти):

См. Также простой метод, который использует стековую память.

std::map<int, MyType1> myMap;

void firstFunctionRunFromThread1()
{
    // Use heap memory so the memory stays allocated.
    MyType1 *mt1 = new MyType1();
    mt1->Test = "Test 1";
    myMap[0] = *mt1;
}

void onlyFunctionRunFromThread2()
{
    /* Now, get a pointer to the object; we can't use stack memory
     * here because the values assigned would be lost as soon as 
     * we try and access them from secondFunctionFromThread1() */
    MyType1 *mt1 = &myMap[0];

    // As expected, this prints "Test 1"
    std::cout << mt1->Test << endl;

    /* Now, because we're assigning to memory on the heap, this will
     * stay assigned until the entire application exits, yay! */
    mt1->Test = "Test 2";
}

void secondFunctionFromThread1()
{
    /* Not sure if using heap memory here is neccecary, but we'll do
     * it anwyay just to play on the safe side... let me know if this
     * is pointless... */
    MyType1 *mt1 = &myMap[0];

    // Hurray, this prints "Test 2"!!! :)
    std::cout << mt1->Test << endl;
}

Простой простой , правильный метод (с использованием стековой памяти правильно):

Благодаря nusi за его ответ .

std::map<int, MyType1> myMap;

void firstFunctionRunFromThread1()
{
    MyType1 mt1;
    mt1.Test = "Test 1";
    myMap[0] = mt1;
}

void onlyFunctionRunFromThread2()
{
    /* Using the & before the variable turns it into a reference, so
     * instead of using stack memory, we use the original memory.
     * NOTE: Is this explanation correct? */
    MyType1 &mt1 = myMap[0];

    // This actually does print "Test 1", so the memory is being accessed.
    std::cout << mt1.Test << endl;

    // We're assigning to the reference, so this works.
    mt1.Test = "Test 2";
}

void secondFunctionFromThread1()
{
    MyType1 mt1 = myMap[0];

    // Prints "Test 1" as expected.
    std::cout << mt1.Test << endl;
}
0
ответ дан 18 December 2019 в 14:51
поделиться

Хотя каждый поток имеет свою "собственную" часть памяти (т.е. - свое собственное пространство "кучи")... память является памятью. Начинание потока ничего не делает к памяти другого потока. Как действительно Распараллеливает B, получают указатель на строку в Потоке A?

Необходимо предоставить больше подробную информацию... Вы помещаете строку на "кучу"? Если это не будет на "куче", то это, вероятно, уйдет, когда Поток A умрет... иначе, у Вас есть ошибка... Отправьте больше!

2
ответ дан 18 December 2019 в 14:51
поделиться

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

9
ответ дан 18 December 2019 в 14:51
поделиться

Да, память остается выделенной.

Поместите точку останова или некоторых входящих в dtor класса, содержащего строку, и посмотрите то, что происходит.

Надеюсь, это поможет

1
ответ дан 18 December 2019 в 14:51
поделиться

Хотя ваш «правильный путь» работает, это слишком много для вашей первоначальной проблемы.

Ниже приведен измените только то, что вам нужно для вашей первоначальной проблемы.

void onlyFunctionRunFromThread2()
{
    MyType1 &mt1 = myMap[0];

   ...

По вашему «правильному пути», именно вы теперь несете ответственность за освобождение памяти, которую вы выделили новой. В вашем исходном примере это было сделано «автоматически» (так сказать).

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

1
ответ дан 18 December 2019 в 14:51
поделиться

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

Строка выделяется на стеке? Если так, у Вас нет общей строки между потоками, даже если тот же код выполняется двумя потоками.

В следующем примере функциональное нечто выполняется двумя потоками:

void foo( void*)
{
   std::string myString;
   // Do something with your string....
}

myString не совместно используется потоками. Каждый поток имеет строковый объект на его собственном стеке.

Так, какова реальная ситуация, к которой Вы обращаетесь?

0
ответ дан 18 December 2019 в 14:51
поделиться

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

0
ответ дан 18 December 2019 в 14:51
поделиться

Как был уже сказан, потоки ничего не делают к Вашей памяти. У них нет частного пространства памяти. Они - просто команды к планировщику Вашей операционной системы для реализации 'параллельного' выполнения 2 или больше функций. Любые 2 функции, которые могут получить доступ к той же переменной, могут сделать так, независимо если они являются поточными (выполняемый рядом) или не (последовательно).

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

Для отладки проблемы, Вы описываете, просто изменяете более основной тип переменной в двух функциях, как интервал. Вероятно, что Ваш контейнер делает некоторое внутреннее копирование данных, как только Вы меняете струну или что-то подобное.

    int i;    // some variable in the scope of both functions

void f1()
{
   while(true)
    {
       i++;
       i %= 128000;
    }
}
void f2()
{
     while(true)
            std::cout 
0
ответ дан 18 December 2019 в 14:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: