سؤال

أنا باستخدام مينغو مع دول مجلس التعاون الخليجي 3.4.5 (مينغو-خاص vista r3).

C بلدي التطبيق يستخدم الكثير من كومة لذلك أنا أتساءل هل هناك أي طريقة أستطيع أن أقول برمجيا كم كومة المتبقية حتى أستطيع نظيفة التعامل مع الوضع إذا وجدت أن أنا على وشك أن ينفد.

إذا كان لا ما هي الطرق الأخرى هل حل المشكلة من المحتمل أن نفاد مساحة مكدس?

ليس لدي أي فكرة ما هو حجم كومة سأبدأ مع ذلك سوف تحتاج إلى تحديد أن برمجيا أيضا.

هل كانت مفيدة؟

المحلول

ريمون تشن (الشيء الجديد القديم) لديه إجابة جيدة على هذا النوع من الأسئلة:

إذا عليك أن تسأل, ربما كنت تفعل شيئا خاطئا.

هنا بعض Win32 التفاصيل على تخصيص مكدس: MSDN.

إذا كنت تعتقد أنك قد تكون محدودة مساحة مكدس, يكاد يكون من المؤكد سوف تكون محدودة الذاكرة الظاهرية المتوفرة, في هذه الحالة, سوف تحتاج إلى العثور على حل آخر.

ماذا تحاول أن تفعل ؟

نصائح أخرى

على getrusage وظيفة يحصل لك الاستخدام الحالي .(انظر man getrusage).

على getrlimit في لينكس سيساعد في جلب حجم مكدس مع RLIMIT_STACK معلمة.

#include <sys/resource.h>
int main (void)
{
  struct rlimit limit;

  getrlimit (RLIMIT_STACK, &limit);
  printf ("\nStack Limit = %ld and %ld max\n", limit.rlim_cur, limit.rlim_max);
}

يرجى إعطاء نظرة man getrlimit.نفس المعلومات يمكن المنال من قبل ulimit -s أو ulimit -a كومة حجم الصف.يكون أيضا نظرة على setrlimit وظيفة التي من شأنها أن تسمح لضبط الحدود.ولكن كما ورد في إجابات أخرى إذا كنت بحاجة إلى ضبط كومة ثم ربما يجب إعادة النظر في التصميم الخاص بك.إذا كنت ترغب في مجموعة كبيرة لماذا لا تأخذ الذاكرة من كومة ?

أخذ عنوان متغير محلي خارج المكدس العمل.ثم في الدعوة المتداخلة يمكنك طرح عنوان محلي آخر لمعرفة الفرق بينهما

size_t top_of_stack;

void Main()
{
  int x=0;
  top_of_stack = (size_t) &x;

  do_something_very_recursive(....)
}

size_t SizeOfStack()
{
  int x=0;
  return top_of_stack - (size_t) &x;
} 

إذا كنت رمز متعددة الخيوط ثم أنت بحاجة للتعامل مع تخزين top_of_stack متغير لكل موضوع على حدة.

تحقق مما إذا كان المترجم الخاص بك يدعم stackavail()

على افتراض انك تعرف حجم كومة كاملة ربما يمكن إضافة بعض رمز التجميع إلى قراءة ESP.
إذا كنت تقرأ ESP وحفظه جانبا في دالة الرئيسي يمكنك مقارنة الحالي ESP إلى ESP لديك في الرئيسية وانظر كم ESP قد تغير.التي سوف تعطيك مؤشرا كم كومة كنت تستخدم.

هذه هي المشكلة لقد تخليت على.مع الكثير من القرصنة و (في الغالب) في الصلاة ، يمكنك الحصول على الحل الذي يعمل في وقت معين على الجهاز.لكن يبدو أن هناك أي لائقة طريقة للقيام بذلك.

سيكون لديك للحصول على كومة موقف وحجم من خارج البرنامج (على لينكس قد تحصل عليه من /proc/<pid>/maps).في البرنامج الخاص بك أو اختبار أين أنت في المكدس.باستخدام المتغيرات المحلية هو ممكن ، ولكن ليس هناك ما يضمن أنها هي في الواقع على المكدس.يمكنك أيضا محاولة للحصول على قيمة من المكدس المؤشر سجل مع الجمعية.

حتى الآن لديك موقع كومة حجمها و الوضع الحالي و تفترض أنك تعرف في أي اتجاه كومة ينمو.عندما أنت ذاهب في كومة تجاوز الوضع ؟ من الأفضل ألا تفعل ذلك بالقرب من النهاية لأن التقدير الخاص بك (أي ، عنوان المتغير المحلي أو قيمة من المكدس المؤشر) هو على الارجح قليلا الإفراط في التفاؤل ؛ فإنه ليس من غير المألوف إلى عنوان الذاكرة يتجاوز مؤشر مكدس.أيضا, لا يوجد لديك فكرة عن كم غرفة على المكدس أي وظيفة (وظائف تسميه) الحاجة.لذلك عليك أن تترك بعض الغرف في نهاية المطاف.

لا أستطيع إلا نصيحة لك أن لا تفعل في هذه الفوضى ومحاولة تجنب عميقة جدا العودية.قد تحتاج أيضا إلى زيادة حجم مكدس;على ويندوز لديك لتجميع هذه إلى الملف القابل للتنفيذ ، على ما أعتقد.

ويندوز:لقد فعلت هذا من قبل باستخدام VirtualQuery وظيفة من Kernel32.dll.لدي فقط مثال في C# ولكن ذلك يوضح الأسلوب:

public static class StackManagement
    {
        [StructLayout(LayoutKind.Sequential)]
        struct MEMORY_BASIC_INFORMATION
        {
            public UIntPtr BaseAddress;
            public UIntPtr AllocationBase;
            public uint AllocationProtect;
            public UIntPtr RegionSize;
            public uint State;
            public uint Protect;
            public uint Type;
        };

        private const long STACK_RESERVED_SPACE = 4096 * 16;

        public unsafe static bool CheckForSufficientStack(UInt64 bytes)
        {
            MEMORY_BASIC_INFORMATION stackInfo = new MEMORY_BASIC_INFORMATION();
            UIntPtr currentAddr = new UIntPtr(&stackInfo);
            VirtualQuery(currentAddr, ref stackInfo, sizeof(MEMORY_BASIC_INFORMATION));

            UInt64 stackBytesLeft = currentAddr.ToUInt64() - stackInfo.AllocationBase.ToUInt64();

            return stackBytesLeft > (bytes + STACK_RESERVED_SPACE);
        }

        [DllImport("kernel32.dll")]
        private static extern int VirtualQuery(UIntPtr lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
    }

راجع للشغل:هذا الرمز يمكن أيضا العثور على ستاكوفيرفلوو على السؤال الذي سألته عندما كان يحاول إصلاح الخلل في التعليمات البرمجية: عملية حسابية أدى إلى تجاوز في غير آمنة C#أدخل رابط الوصف هنا

ربما هذا سوف يساعد على منصة ويندوز فقط:

في رأس PE (IMAGE_NT_HEADERS) من exe الخاص بك وهناك بعض الوثائق مثل:

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

typedef struct _IMAGE_OPTIONAL_HEADER {
    ...
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    ...
}

هناك طريقة بسيطة للحصول على هذه القيم:باستخدام GetModuleHandle(NULL) سوف تعطيك imagebase (التعامل مع) من جهاز وحدة معالجة حيث ستجد IMAGE_DOS_HEADER هيكل والتي سوف تساعدك على العثور على IMAGE_NT_HEADERS هيكل (imagebase+IMAGE_DOS_HEADER.e_lfanew) -> IMAGE_NT_HEADERS ، و هناك ستجد تلك المجالات: SizeOfStackReserve و SizeOfStackCommit.

الحد الأقصى الفضائية أن التشغيل سيتم تخصيص الخاص بك كومة SizeOfStackReserve.

إذا كنت النظر في محاولة هذا اسمحوا لي أن أعرف وأنا سوف يساعدك.هناك طريقة للحصول على حجم كومة المستخدمة في نقطة معينة.

على لينكس ، تسمونه getrusage والتحقق عاد البنية rusage هو ru_isrss الأعضاء (لا يتجزأ مشترك حجم مكدس).

من مينغو موقع و سورس الموقع تتبع بقع أرى أنه في شهر مايو من عام 2008 كان هناك بعض الترقيع به في جميع أنحاء getrusage و يبدو أنه كان يؤيد عموما لفترة طويلة.يجب عليك التحقق بعناية عن أي محاذير من حيث كم نموذجية لينكس يعتمدها مينغو.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top