Question

J'utilise MinGW GCC 3.4.5 (mingw-spécial vista r3).

Mon C application utilise beaucoup de pile donc je me demandais est-il possible que je peux dire par programmation combien pile est du reste si je peux proprement gérer la situation si je trouve que je suis sur le point de lancer.

Si non quelles sont les autres façons accepteriez-vous de travailler autour de la problématique de potentiellement en cours d'exécution hors de l'espace de pile?

Je n'ai aucune idée de ce que la taille de la pile, je vais commencer avec donc identifier que par programmation aussi.

Était-ce utile?

La solution

Raymond Chen (Le Vieux Chose De Nouveau) a une bonne réponse à ce genre de question:

Si vous vous posez, vous êtes probablement fait quelque chose de mal.

Voici quelques Win32 détails sur l'allocation de pile: MSDN.

Si vous pensez que vous pourriez être limité par l'espace de pile, vous aurez presque certainement être limité par la mémoire virtuelle disponible, dans ce cas, vous aurez besoin de trouver une autre solution.

Qu'est-ce exactement que vous essayez de faire?

Autres conseils

Le getrusage fonction vous fait de l'utilisation actuelle .(voir man getrusage).

L' getrlimit dans Linux permettrait de récupérer la taille de la pile avec le RLIMIT_STACK le paramètre.

#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);
}

Merci de donner un coup d'oeil à man getrlimit.La même information peut être récupérée par ulimit -s ou ulimit -a la taille de la pile de ligne.Aussi jeter un oeil à setrlimit fonction qui permettrait de définir les limites.Mais comme mentionné dans les autres réponses, si vous avez besoin d'ajuster pile, alors vous devriez probablement envisager de re votre conception.Si vous voulez un grand tableau, pourquoi ne pas prendre la mémoire dans le tas ?

Prendre l'adresse d'une variable locale au large de la pile de travail.Alors en plus imbriqués appel vous pouvez soustraire l'adresse d'un autre local pour trouver la différence entre eux

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;
} 

Si vous le code est multi-thread, alors vous devez traiter avec le stockage de la top_of_stack variable sur une base par thread.

vérifiez si votre compilateur prend en charge stackavail()

En supposant que vous connaissez la taille de la pile complète, vous pourriez ajouter un peu de montage code pour lire ESP.
Si vous lisez l'ESP et de l'enregistrer à part dans la fonction principale, vous pouvez comparer l'état actuel de l'ESP l'ESP vous avez en principal et de voir combien l'ESP a changé.Cela vous donnera une indication de la façon dont beaucoup de la pile que vous avez l'habitude.

C'est un problème que j'ai abandonné.Avec beaucoup de piratage et (surtout) la prière, vous pouvez obtenir une solution qui fonctionne à un moment donné sur une machine donnée.Mais en général, il semble y avoir aucune manière décente pour ce faire.

Vous aurez à obtenir la pile de la position et de la taille de l'extérieur de votre programme (sur Linux vous pouvez l'obtenir à partir d' /proc/<pid>/maps).Dans votre programme, vous devez en quelque sorte de test où vous êtes à la pile.Utilisation de variables locales est possible, mais il n'y a pas de véritable garantie qu'ils sont en fait sur la pile.Vous pouvez aussi essayer d'obtenir la valeur du registre de pointeur de pile avec un peu de montage.

Alors maintenant, vous avez l'emplacement de la pile, de sa taille et de la position actuelle et vous suppose que vous savez dans quelle direction la pile augmente.Quand allez-vous dans la pile de débordement de la mode?Il vaut mieux ne pas le faire fermer à la fin parce que votre estimation (c'est à direl'adresse de la variable locale ou de la valeur du pointeur de pile) est sans doute un peu trop optimiste;il n'est pas rare d'adresse de la mémoire au-delà du pointeur de pile.Aussi, vous n'avez pas la moindre idée de la façon dont beaucoup de place sur la pile une fonction donnée (et les fonctions qu'il appelle) besoin.Ainsi, vous aurez à quitter tout à fait un peu de place à la fin.

Je ne peux que vous conseiller de ne pas faire entrer dans ce désordre et essayer d'éviter de très profond de la récursivité.Vous pouvez également augmenter la taille de votre tapis;sur Windows, vous devez compiler ce dans l'exécutable, je crois.

Pour windows:Je l'ai fait avant d'utiliser le VirtualQuery fonction de Kernel32.dll.Je n'ai qu'un exemple en C#, mais il montre la technique:

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);
    }

BTW:Ce code peut également être trouvée sur StackOverflow sur une autre question à laquelle j'ai demandé quand j'ai essayé de corriger un bug dans le code: Opération arithmétique a entraîné un dépassement dangereux C#entrez description du lien ici

peut-être que cela aidera pour la plateforme Windows uniquement:

dans l'en-tête PE (IMAGE_NT_HEADERS) de votre exe il y a certains dossiers tels que:

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;
    ...
}

Il existe un moyen simple pour obtenir ces valeurs:à l'aide de GetModuleHandle(NULL) vous donnera l'imagebase (poignée) de votre module, l'adresse où vous trouverez un IMAGE_DOS_HEADER structure qui vous aidera à trouver la IMAGE_NT_HEADERS structure (imagebase+IMAGE_DOS_HEADER.e_lfanew) -> IMAGE_NT_HEADERS, et là, vous trouverez les champs: SizeOfStackReserve et SizeOfStackCommit.

Le montant maximum de l'espace que l'OS va allouer pour votre pile est SizeOfStackReserve.

Si vous songez à essayer le présent, laissez-moi savoir et je vais vous aider.Il y a un moyen pour obtenir la taille de pile utilisé dans un certain point.

Sur Linux, vous pouvez appeler getrusage et vérifier le retour de l'struct rusage du ru_isrss membre (partie intégrante de partage de la taille de la pile).

À partir de la MINGW site et de son site de sourceforge du suivi des patchs, je vois qu'en Mai 2008, il y a quelques correctifs de faire de l'getrusage et il semble que c'est généralement pris en charge pour un certain temps.Vous devez vérifier soigneusement par les restrictions en termes de combien de Linux typique fonctionnalité est prise en charge par MinGW.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top