Канал ожога "|" является "поразрядным" или и должен только использоваться, когда Вы знаете то, что Вы делаете. Двойной канал "||" является логическим или и может использоваться в логических операторах, как "x == 0 || x == 1".
Вот пример того, что поразрядное или делает: если a=0101 и b=0011, то a|b=0111. Если Вы будете иметь дело с логической системой, которая рассматривает любого ненулевого как верного, то поразрядное или будет действовать таким же образом как логическое или, но это - дубликат (поразрядно и, "&";) НЕ будет. Также поразрядное или не выполняет оценку короткого замыкания.
Просто прочтите% esp и помните, что его значение уменьшается. Вы уже знаете свой максимальный размер по умолчанию из среды, а также начальную точку ваших потоков.
gcc имеет отличную поддержку сборки, в отличие от некоторых других.
Это очень сильно зависит от вашей ОС и его управление памятью. В Linux вы можете использовать procfs . Это что-то вроде / proc / $ PID / memory. Я сейчас не на Linux.
GCC обычно добавляет 16 битов для регистров (чтобы вернуться к контексту функции, из которого идет ссылка) в стек-кадр. Обычно вы можете получить больше информации о том, как именно компилируется программа, дизассемблировав ее. Или используйте -S для получения сборки.
Существует API pthread для определения расположения стека:
#include <pthread.h>
void PrintStackInfo (void)
{ pthread_attr_t Attributes;
void *StackAddress;
int StackSize;
// Get the pthread attributes
memset (&Attributes, 0, sizeof (Attributes));
pthread_getattr_np (pthread_self(), &Attributes);
// From the attributes, get the stack info
pthread_attr_getstack (&Attributes, &StackAddress, &StackSize);
// Done with the attributes
pthread_attr_destroy (&Attributes);
printf ("Stack top: %p\n", StackAddress);
printf ("Stack size: %u bytes\n", StackSize);
printf ("Stack bottom: %p\n", StackAddress + StackSize);
}
На i386 стек начинается снизу и растет кверху.
Итак, вы знаете, что у вас есть ($ ESP - StackAddress) доступны байты.
В моей системе у меня есть оболочка вокруг pthread_create (), поэтому каждый поток запускается в моей частной функции. В этой функции я нахожу стек, как описано выше, затем нахожу неиспользуемую часть, затем инициализирую эту память с помощью отличительного шаблона (или «Паттона», как сказал бы мой тесть из Сомервилля, Массачусетс)
Затем, когда я хочу узнать, какая часть стека была использована, я начинаю сверху и ищу снизу первое значение, не соответствующее моему шаблону.
Вы можете увидеть состояние стека виртуальных область памяти, просмотрев / proc /
. Vma стека автоматически уменьшается при использовании большего количества спа стека. Вы можете проверить, сколько места в стеке вы действительно используете, проверив, как далеко % esp
находится от верхнего предела области стека на smaps
(по мере роста стека). Вероятно, первым пределом, которого вы достигнете, если вы используете слишком много места в стеке, будет предел, установленный ulimit
.
Но всегда помните, что эти низкоуровневые детали могут изменяться без какого-либо уведомления. Не ожидайте, что все версии ядра Linux и все версии glibc будут вести себя одинаково. Я бы никогда не заставил свою программу полагаться на эту информацию.
Если ваше приложение должно быть уверено, что оно может использовать X МБ памяти, обычно процесс выделяет ее во время запуска (и не запускается, если не может выделить минимальные требования) .
Это, конечно, означает, что приложение должно использовать свою собственную логику управления памятью.
В Tcl когда-то была проверка стека, чтобы избежать сбоев из-за неограниченной рекурсии или других проблем вне стека. Не был слишком портативным, например, разбился на одной из BSD ..., но вы могли попытаться найти код, который они использовали.