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

#.net #c #timeout #global-variables #destructor

#.net #c #тайм-аут #глобальные переменные #деструктор

Вопрос:

В моем приложении C смешанного режима я замечаю следующие странные эффекты:

  • Если я запускаю исполняемый файл вне Visual Studio, все неуправляемые глобальные переменные правильно уничтожаются.
  • Если я запускаю исполняемый файл вне Visual Studio, а затем подключаю отладчик, все неуправляемые глобальные переменные правильно уничтожаются.
  • При Запуске исполняемого файла внутри отладчика Visual Studio не все неуправляемые глобальные переменные, похоже, уничтожены.

Я прочитал это.У Net есть 2-секундный тайм-аут для очистки. Означает ли это полное уничтожение неуправляемой глобальной переменной? Или это для каждого деструктора?

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

Есть ли способ изменить этот 2-секундный тайм-аут из приложения? Проблема в том, что если не все глобальные переменные уничтожены, моя система обнаружения утечек памяти сообщит о большом количестве утечек памяти.

Редактировать:

Это пример программы, показывающий проблему.

Поскольку я хотел создать приложение смешанного режима, я написал отдельный main (скомпилированный изначально) и отдельную функцию ‘add’ (скомпилированный управляемый). Это основная:

 #include <iostream>
#include <windows.h>

extern int add(int,int);

class X
   {
   public:
      X(char *name) : m_name(name) {std::cout << "Constructing " << m_name << std::endl;}
      ~X() {Sleep(1000); std::cout << "Destructing " << m_name << std::endl;}
   private:
      char *m_name;
   };

X x1("x1");
X x2("x2");
X x3("x3");
X x4("x4");
X x5("x5");

int main()
{
std::cout << "In beginning of main" << std::endl;
int i = add(1,2);
std::cout << i << std::endl;
std::cout << "At end of main" << std::endl;
}
  

И это add.cpp файл:

 int add (int one, int two)
{
int result = one;
result  = two;
return resu<
}
  

Они компилируются и связываются с помощью этих команд (с использованием VS2010 и .Net 4.0):

 cl /c /EHsc /Od /Zi main.cpp
cl /c       /Od /Zi /clr add.cpp
link /debug /debugtype:cv main.obj add.obj mscoree.lib nochkclr.obj /nodefaultlib:libcmt.lib
  

Это результат, если приложение запущено:

 Constructing x1
Constructing x2
Constructing x3
Constructing x4
Constructing x5
In beginning of main
3
At end of main
Destructing x5
  

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

Если я уменьшу время ожидания с 1000 мс до 500 мс, глобальные переменные x5, x4 и x3 будут уничтожены, но затем это также остановится.

Я загрузил файлы в http://www.mediafire.com/?gil2hm2d3cw1zmz, поэтому, если вы хотите протестировать это, вам не нужно копировать / вставлять или перепечатывать все снова.

РЕДАКТИРОВАТЬ: Немного изменил заголовок, чтобы теперь было более понятно, что у нас есть фактическая причина проблемы.

Комментарии:

1. Это интересный вопрос. Я думаю, люди захотят подключиться, если бы в вопросе была минимальная рабочая демонстрация этого 🙂

2. Хорошо, пример приложения теперь подключен к Сети.

3. Жаль, что я могу ответить только на 1 этот вопрос. Теперь это отличный вопрос!

Ответ №1:

Хм, подтверждаю проблему. Мне нужно подумать / прочитать больше об этом. На самом деле это начинает выглядеть как ошибка.


Обратите внимание, что я ни разу не запускал ничего из этого с отладкой, потому что моя установка VS каким-то образом заблокирована. Слава за выполнение сборки из командной строки!

Для справки, вот мой первоначальный запуск (без перекомпиляции, только ваш двоичный файл) на Win7-64, .NET 4.0, двух ядрах процессора и 1 ГБ оперативной памяти):

 C:stacko>.main.exe
Constructing x1
Constructing x2
Constructing x3
Constructing x4
Constructing x5
In beginning of main
3
At end of main
Destructing x5
Destructing x4
Destructing x3
  

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

 C:stacko>cl /c /EHsc /Od /Zi main.cpp
Microsoft (R) 32-bit C/C   Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp


C:stacko>link main.obj
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

C:stacko>.main.exe
Constructing x1
Constructing x2
Constructing x3
Constructing x4
Constructing x5
In beginning of main
At end of main
Destructing x5
Destructing x4
Destructing x3
Destructing x2
Destructing x1
  

Проверка: подтверждена.

Ответ №2:

@sehe: Ваша собственная сборка не работает в смешанном режиме! Вот почему он уничтожается должным образом.

Если вы хотите создать приложение смешанного режима, вам необходимо добавить параметр /clr paremeter. Более того, невозможно объединить /clr с /EHsc, вы должны использовать /EHa

 cl /c /clr /EHa /Od /Zi main.cpp
  

Однако я сталкиваюсь с той же проблемой, что и автор … у кого-нибудь есть решение?