Segfault на переполнении стека

Все правила изложены здесь здесь .

Для get это явно нарушает правило «Пропустить ненужные слова». Если метод возвращает что-то, сайт вызова будет знать, что он используется для получения некоторого значения. Вам не нужно повторять эту идею. Вы можете рассмотреть возможность превращения этого в вычисляемое свойство, если параметры не требуются.

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

func getFoo() -> Int {
    ...
}

func setFoo(_ foo: Int) {
    ...
}

Это довольно хороший признак того, что его можно превратить в вычисляемое свойство:

var foo: Int {
    get { ... }
    set { ... }
}

Хороший пример где уместно иметь set - метод UIButton.setTitle. Он принимает два параметра, поэтому вычисляемое свойство не будет работать.

Для is это явно соответствует правилу «Использование булевых методов и свойств следует читать как утверждения о получателе». Так что да, вы должны использовать его для логических членов.

12
задан 17 September 2008 в 08:43
поделиться

6 ответов

Можно на самом деле поймать условие для переполнения стека с помощью обработчиков сигналов.

, Чтобы сделать это, необходимо сделать две вещи:

  • Установка обработчик сигналов для SIGSEGV (segfault) использующий sigaction, чтобы сделать этот набор флаг SO_ONSTACK. Это дает ядру команду использовать альтернативный стек при поставке сигнала.

  • Вызов sigaltstack () для установки альтернативного стека, который будет использовать обработчик для SIGSEGV.

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

41
ответ дан 2 December 2019 в 03:03
поделиться

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

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

, Если Вы хотите автоматизированную справку, можно использовать gcc's - опция Wstack-средства-защиты, которая определит некоторое переполнение во времени выполнения и прервет программу.

valgrind хорош для ошибок динамического выделения памяти, но не для ошибок стека.

0
ответ дан 2 December 2019 в 03:03
поделиться

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

1
ответ дан 2 December 2019 в 03:03
поделиться

"Ядро" (это - на самом деле не ядро, выполняющее Ваш код, это - ЦП), не знает, как Ваш код ссылается на память, которой это, как предполагается, не касается. Это только знает, что Вы пытались сделать это.

код:

char *x = alloca(100);
char y = x[150];

не может действительно быть оценен ЦП как Вы пытающийся получить доступ вне границ x.

, можно поразить тот же самый адрес:

char y = *((char*)(0xdeadbeef));

BTW, я препятствовал бы использованию alloca, так как стек имеет тенденцию быть намного более ограниченным, чем "куча" (используйте malloc вместо этого).

7
ответ дан 2 December 2019 в 03:03
поделиться

Переполнение стека является отказом сегментации. Как в Вы повредили данные границы памяти, что Вы были первоначально выделены. Стек конечного размера, и Вы превысили его. Можно читать больше об этом в Википедия

Кроме того, одна вещь, которую я сделал для проектов в прошлом, запись мой собственный обработчик сигналов к segfault (взгляд на сигнал (2) страницы справочника). Я обычно ловил сигнал и выписывал "Фатальную ошибку, произошел" с консолью. Я сделал некоторый дальнейший материал с флагами контрольной точки и отладку.

для отладки segfaults, можно запустить программу в GDB. Например, следующая программа C будет segfault: #segfault.c #include #include

int main() 
{
        printf("Starting\n");
        void *foo=malloc(1000);
        memcpy(foo, 0, 100); //this line will segfault
        exit(0);
}

, Если я компилирую его как так:

gcc -g -o segfault segfault.c 

и затем выполненный это как так:

$ gdb ./segfault
GNU gdb 6.7.1
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run
Starting program: /tmp/segfault 
Starting

Program received signal SIGSEGV, Segmentation fault.
0x4ea43cbc in memcpy () from /lib/libc.so.6
(gdb) bt
#0  0x4ea43cbc in memcpy () from /lib/libc.so.6
#1  0x080484cb in main () at segfault.c:8
(gdb) 

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

5
ответ дан 2 December 2019 в 03:03
поделиться

Некоторые комментарии полезны, но проблема не имеет ошибок распределения памяти. Это в коде нет никакой ошибки. Это - настоящая неприятность в Фортране, где время выполнения выделяет временные ценности на стеке. Таким образом команда, такая как запись (fp) x, y, z может инициировать, segfault без предупреждения. Техническая поддержка для компилятора intel Fortran говорит, что нет никакого способа, которым библиотека времени выполнения может распечатать более полезное сообщение. Однако, если Miguel прав, чем это должно быть возможно, как он предполагает. Так большое спасибо. Остающийся вопрос затем состоит в том, как я во-первых нахожу адрес отказа seg и фигуры, если это прибыло из переполнения стека или некоторой другой проблемы.

Для других, которые находят эту проблему, существует флаг компилятора, который помещает временный varibles выше определенного размера на "куче".

0
ответ дан 2 December 2019 в 03:03
поделиться
Другие вопросы по тегам:

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