Я пытаюсь выяснить, что такое ограничение размера стека, когда функция MATLAB вызывает функцию в DLL.
Есть ли способ настроить предел?Что такое ограничение стека при вызове функции MATLAB в DLL
Я использую loadlibrary
и calllib
функции функции вызова, реализованные в C (в библиотеке динамической компоновки).
Я создал тест, чтобы выяснить предел стека.
Я использую MATLAB 2016a (64 бит) и Visual Studio 2010 для создания библиотеки DLL.
Вот мой MATLAB исходный код:
loadlibrary('MyDll','MyDll.h')
size_in_bytes = 1000000;
res = calllib('MyDll', 'Test', size_in_bytes);
if (res == -1)
disp(['Stack Overflow... (size = ', num2str(size_in_bytes), ')']);
else
disp(['Successful stack allocation... (size = ', num2str(size_in_bytes), ')']);
end
unloadlibrary MyDll
Вот мой исходный код C:
MyDll.h
// MyDll.h : DLL interface.
#ifndef MY_DLL_H
#define MY_DLL_H
#ifdef MY_DLL_EXPORTS
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif
extern MY_DLL_API int Test(int size);
#endif
MyDll.c
// MyDll.c
#include "MyDll.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
//Allocate <size> bytes in stack using _alloca(size).
//Return 0 if OK.
//Return (-1) in case of stack overflow.
int Test(int size)
{
//Not allocated on the stack...
static wchar_t errorMsg[100];
static wchar_t okMsg[100];
int errcode = 0;
void *pData = NULL;
//Prepare messages from advance.
swprintf_s(errorMsg, 100, L"Stack Overflow (size = %d)", size);
swprintf_s(okMsg, 100, L"Successful stack allocation (size = %d)", size);
__try
{
pData = _alloca(size);
}
// If an exception occurred with the _alloca function
__except (GetExceptionCode() == STATUS_STACK_OVERFLOW)
{
MessageBox(NULL, errorMsg, TEXT("Error"), MB_OK | MB_ICONERROR);
// If the stack overflows, use this function to restore.
errcode = _resetstkoflw();
if (errcode)
{
MessageBox(NULL, TEXT("Could not reset the stack!"), TEXT("Error"), MB_OK | MB_ICONERROR);
_exit(1);
}
pData = NULL;
};
if (pData != NULL)
{
//Fill allocated buffer with zeros
memset(pData, 0, size);
MessageBox(NULL, okMsg, TEXT("OK"), MB_OK);
return 0;
}
return -1;
}
Блок __try
и __except
взят из примера Microsoft:
https://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
DLL флаги компилятора:
/Zi /nologo /W4 /WX- /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_USRDLL" /D "MY_DLL_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MTd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"x64\Debug\MyDll.pch" /Fa"x64\Debug\" /Fo"x64\Debug\" /Fd"x64\Debug\vc100.pdb" /Gd /errorReport:queue
DLL компоновщика флаги:
/OUT:"x64\Debug\MyDll.dll" /INCREMENTAL:NO /NOLOGO /DLL "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"x64\Debug\MyDll.dll.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\Tmp\MyDll\x64\Debug\MyDll.pdb" /SUBSYSTEM:CONSOLE /PGD:"c:\Tmp\MyDll\x64\Debug\MyDll.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X64 /ERRORREPORT:QUEUE
Я выполнил код MATLAB, используя различные значения size_in_bytes
:
size_in_bytes = 1000000
: Pass!
size_in_bytes = 10000000
: Pass!
size_in_bytes = 50000000
: Pass!
size_in_bytes = 60000000
: Pass!
size_in_bytes = 70000000
: Переполнение стека!
Похоже, что в моей системе ограничение составляет около 64MByte (но я не знаю, верно ли это число для всех систем).
Я попытался изменить размер стека из Matlab.exe
с помощью editbin инструмента.
Я попробовал следующую команду (например):
editbin /STACK:250000000 "c:\Program Files\MATLAB\R2016a\bin\matlab.exe"
.
Этот параметр устанавливает размер стека в байтах и принимает аргументы в десятичной или C-языковой нотации. Параметр/STACK применяется только к исполняемому файлу.
Это, кажется, не влияет ...
Размер стека установлен во время выполнения, поэтому вам нужно проверить размер стека, выделяемого вашими os. Кстати, вы даете мне сердечный приступ с '__try' в C. – Stargateur
Так как я могу установить размер в Windows 10? – Rotem