что такое “выравнивание стека”?

У меня была такая же проблема, мы можем решить проблему без какого-либо убийства, мы всегда забываем закрыть интерфейсы, которые мы использовали в классе Microsoft.Office.Interop.Excel, так что вот фрагмент кода и следуйте структуре и образом очистились объекты, также следите за интерфейсом «Листы» в коде, это главный виновник, который мы часто закрываем приложением, рабочей книгой, книгами, диапазоном, листом, но мы забываем или неосознанно не выпускаем объект «Листы» или используемый интерфейс, поэтому вот код:

               Microsoft.Office.Interop.Excel.Application app = null;
        Microsoft.Office.Interop.Excel.Workbooks books = null;
        Workbook book = null;
        Sheets sheets = null;
        Worksheet sheet = null;
        Range range = null;

        try
        {
            app = new Microsoft.Office.Interop.Excel.Application();
            books = app.Workbooks;
            book = books.Add();
            sheets = book.Sheets;
            sheet = sheets.Add();
            range = sheet.Range["A1"];
            range.Value = "Lorem Ipsum";
            book.SaveAs(@"C:\Temp\ExcelBook" + DateTime.Now.Millisecond + ".xlsx");
            book.Close();
            app.Quit();
        }
        finally
        {
            if (range != null) Marshal.ReleaseComObject(range);
            if (sheet != null) Marshal.ReleaseComObject(sheet);
            if (sheets != null) Marshal.ReleaseComObject(sheets);
            if (book != null) Marshal.ReleaseComObject(book);
            if (books != null) Marshal.ReleaseComObject(books);
            if (app != null) Marshal.ReleaseComObject(app);
        }
44
задан Stu Thompson 11 November 2009 в 15:19
поделиться

4 ответа

Выравнивание переменных в памяти (краткая история).

В прошлых компьютерах имел шину данных на 8 битов. Это означает, что каждый такт 8 битов информации мог быть обработан. Который был прекрасен тогда.

Тогда прибыл компьютеры на 16 битов. Из-за совместимости сверху вниз и других проблем, байт на 8 битов был сохранен, и слово на 16 битов было представлено. Каждое слово составляло 2 байта. И каждый такт 16 битов информации мог быть обработан. Но это создало небольшую проблему.

Позволяют нам посмотреть на карту распределения памяти:

+----+
|0000| 
|0001|
+----+
|0002|
|0003|
+----+
|0004|
|0005|
+----+
| .. |

В каждом адресе существует байт, к которому можно получить доступ индивидуально. Но слова могут только быть выбраны даже в адресах. Таким образом, если мы читаем слово в 0000, мы читаем байты в 0000 и 0001. Но если мы хотим считать слово в положении 0001, нам нужен два доступа для чтения. Сначала 0000,0001 и затем 0002,0003 и мы только сохраняем 0001,0002.

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

, Например, если у нас есть структура с полем (B) байта и полем (W) слова (и очень наивный компилятор), мы получаем следующее:

+----+
|0000| B
|0001| W
+----+
|0002| W
|0003|
+----+

, Который не является забавой. Но при использовании выравнивания слов мы находим:

+----+
|0000| B
|0001| -
+----+
|0002| W
|0003| W
+----+

Здесь память принесена в жертву за скорость доступа.

можно предположить, что при использовании двойного слова (4 байта) или квадратического слова (8 байтов) это еще более важно. Вот почему с большинством современных компиляторов Вы можете, выбрал, какое выравнивание Вы используете при компиляции программы.

115
ответ дан derpda 26 November 2019 в 21:41
поделиться

Некоторые архитектуры ЦП требуют определенного выравнивания различных типов данных и выдадут исключения, если Вы не соблюдаете это правило. В стандартном режиме x86 не требует этого для типов основных данных, но может пострадать, потери производительности (проверьте www.agner.org на подсказки по оптимизации низкого уровня).

Однако система команд SSE (часто используемый для высокоэффективного) аудио/видео обработка имеет строгие требования выравнивания и выдаст исключения, при попытке использовать ее на невыровненных данных (если Вы не используете, на некоторых процессорах, намного медленнее невыровненные версии).

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

РЕДАКТИРОВАНИЕ : что касается того, почему происходит исключение, стандартная программа в DLL, вероятно, хочет использовать инструкции SSE относительно некоторых временных данных стека и сбои, потому что два различных компилятора не договариваются о соглашениях о вызовах.

11
ответ дан snemarch 26 November 2019 в 21:41
поделиться

IIRC, выравнивание стека состоит в том, когда переменные помещаются в стек, "выровненный" к конкретному числу байтов. Таким образом, при использовании выравнивания стека на 16 битов каждая переменная на стеке собирается начать с байта, который является кратным 2 байтам от текущего указателя вершины стека в функции.

Это означает что при использовании переменной, которая является < 2 байта, такие как символ (1 байт), будут 8 битами неиспользованного "дополнения" между ним и следующей переменной. Это позволяет определенные оптимизации с предположениями на основе переменных местоположений.

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

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

11
ответ дан MSalters 26 November 2019 в 21:41
поделиться

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

// Some compilers won't align this as it's on the stack...
int __declspec(align(32)) needsToBe32Aligned = 0;
// Change to
static int __declspec(align(32)) needsToBe32Aligned;
needsToBe32Aligned = 0;

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

2
ответ дан Dan Olson 26 November 2019 в 21:41
поделиться
Другие вопросы по тегам:

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