LINUX.ORG.RU

C + random + array + segfault

 , , ,


0

1
#include <stdio.h>

main() {
    srand(time(NULL));
    int arr[9999999];
    int i;
    for(i=0; i<9999999; i++) {
        arr[i] = rand() % 99999999;
        printf("%d \n", arr[i]);
    }
}

решил откопать книгу по Си. Первый пример, ловлю segfault. Что не так? вывод strace:

execve("./a.out", ["./a.out"], [/* 47 vars */]) = 0
brk(0)                                  = 0x87a1000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7716000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=111260, ...}) = 0
mmap2(NULL, 111260, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76fa000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0\227\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1790836, ...}) = 0
mmap2(NULL, 1591836, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7575000
mprotect(0xb76f3000, 4096, PROT_NONE)   = 0
mmap2(0xb76f4000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17e) = 0xb76f4000
mmap2(0xb76f7000, 10780, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb76f7000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7574000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75746c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb76f4000, 8192, PROT_READ)   = 0
mprotect(0xb7738000, 4096, PROT_READ)   = 0
munmap(0xb76fa000, 111260)              = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Ошибка сегментирования
ничего не понимаю :)

Deleted

Последнее исправление: CYB3R (всего исправлений: 2)

за стек выкатываешься, сейчас он обычно от 8 до 16 мб по умолчанию. У тебя явно много больше.

mashina ★★★★★
()
Ответ на: комментарий от Krieger_Od

что ты имеешь в виду? почему?

Deleted
()
Ответ на: комментарий от mashina

ок, понял. увеличил с ulimit, всё работает. Почему на другом языке всё ок, а тут пришлось так делать?

Deleted
()
Ответ на: комментарий от mashina

аналогичный код на fpc.

Если кратко - не умеешь на этом языке писать.

бесспорно. просто хотел переписать алгоритм на сях. столкнулся с этим, возник вопрос: почему тут пришлось так делать? а как раньше работало без ulimit -s?

Deleted
()
Ответ на: комментарий от Deleted

Это чего, паскаль чтоли? Оно размещает массивы не на стеке.

а как раньше работало без ulimit -s?

Раньше ничего не работало. Неужели так трудно понять, что си и паскаль разные языки с разными нюансами? Нельзя просто так скопипастить код из языка X в Y и ожидать что всё будет хорошо.

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от Deleted

Модеры, добавьте тэг «я познаю мир» :) Без обид, ты просто не в курсе многих нюансов. Если реально хочешь научиться, а не только пообщаться на ЛОРе, изучай самостоятельно. Прочитай какую-нибудь базовую книгу по Си, и потом CERT C Secure Coding Standards.

Krieger_Od ★★
()
Ответ на: комментарий от Krieger_Od

Прочитай какую-нибудь базовую книгу по Си, и потом CERT C Secure Coding Standards.

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

Deleted
()
Ответ на: комментарий от Deleted

Надо выделять на куче с помощью malloc. Разберись лучше как работает компьютер, а то C он такой!

stopitplease
()

int arr[9999999];

Ты точно С изучаешь? Ужас-то какой! Это кто тебя такому безобразию научил?

Eddy_Em ☆☆☆☆☆
()

Раньше были надписи типа stack overflow не?

quest ★★★★
()

cpp тут для красоты?

deterok ★★★★★
()

Вынеси определение массива из main или добавь static.

ziemin ★★
()

чем и какими опциями собрать чтобы получить stack overflow а не segmentation fault?

gcc -fstack-protector-all -fstack-check
clang -fsanitize=address -fsanitize=bounds

ничего не ловит, а ведь может быть полезно

quest ★★★★
()
Последнее исправление: quest (всего исправлений: 1)
Ответ на: комментарий от quest

Что такое «stack overflow»? SIGSEGV - стандартный сигнал, который процесс получает в таких случаях.

(В FreeBSD, по крайней мере,) на минимально (по адресу) возможной верхушке стека библиотека, рулящая нитями, создает guard page с флагами доступа PROT_NONE. Поэтому когда стек слишком сильно разрастается, вылазя на эту страницу, и возникает segmentation fault

stopitplease
()
Ответ на: комментарий от stopitplease

Что такое «stack overflow»?

Вероятно специальный код который отслеживает выход за границу стека и гасит процесс с более понятным сообщением

quest ★★★★
()
Ответ на: комментарий от stopitplease

(В FreeBSD, по крайней мере,) на минимально (по адресу) возможной верхушке стека библиотека, рулящая нитями, создает guard page с флагами доступа PROT_NONE. Поэтому когда стек слишком сильно разрастается, вылазя на эту страницу, и возникает segmentation fault

Это иногда спасает только от функций с небольшим потреблением стека, в пределах страницы и менее, в случае ТС никакие страницы не помогут. Ему просто повезло, что после стека ниже на 20-30 мб ничего больше не замаплено с правами на запись. Для основного потока так везти вероятно будет всегда, т.к. его обычно размещают в конце.

mashina ★★★★★
()

int arr[9999999];

ты упорот?

emulek
()
Ответ на: комментарий от Deleted

Почему на другом языке всё ок, а тут пришлось так делать?

а ты static сделай. И всё будет ОК (правда сам бинарник будет 99999999 байт + ещё немного).

А вообще в сишке такое malloc'ом делают.

emulek
()
Ответ на: комментарий от quest

чем и какими опциями собрать чтобы получить stack overflow а не segmentation fault?

компьютер постарше купи в антикварной лавке. И будет у тебя сегфолт. Ну можно наверное и TurboC в DosBox попробовать.

emulek
()
Ответ на: комментарий от mashina

По-моему, страница и поможет. Он же пишет последовательно небольшие объекты по 4 байта размером. Если бы он писал с большими промежутками, мог бы и проскочить

stopitplease
()
Ответ на: комментарий от quest

Вероятно специальный код который отслеживает выход за границу стека и гасит процесс с более понятным сообщением

по стандарту это UB. Скажи спасибо, что у тебя диск не отформатировался.

emulek
()
Ответ на: комментарий от emulek

правда сам бинарник будет 99999999 байт + ещё немног

.bss секция.

stopitplease
()
Ответ на: комментарий от stopitplease

Он сразу начинает писать за пределами стека. Первый элемент массива находится примерно на base + sizeof(int) * 9999999 + небольшая константа

mashina ★★★★★
()
Ответ на: комментарий от mashina

base + sizeof(int) * 9999999 + небольшая константа

тут, конечно же, должно быть base - (sizeof(int) * 9999999 + небольшая константа)

mashina ★★★★★
()
Ответ на: комментарий от stopitplease

Дева Мария и святые угодники, какая чушь

а где в стандарте написано, какое сообщение выдавать при переполнении стека? Детка, почитай про то, что такое UB.

emulek
()
Ответ на: комментарий от emulek

компьютер постарше купи в антикварной лавке. И будет у тебя сегфолт. Ну можно наверное и TurboC в DosBox попробовать.

ты не поверишь я писал и на turboc и на watcom и на djgpp. хорошо что valgrind четко говорит - не хватает стека

quest ★★★★
()
Ответ на: комментарий от stopitplease

придурок, узнай, что такое НЕОПРЕДЕЛЁННОЕ ПОВЕДЕНИЕ.

emulek
()
Ответ на: комментарий от emulek

по стандарту это UB. Скажи спасибо, что у тебя диск не отформатировался.

должна быть опция которая будет отслеживать выделение стека и остановит процесс с более вменяемым сообщением

quest ★★★★
()
Ответ на: комментарий от quest

ты не поверишь я писал и на turboc и на watcom и на djgpp.

лабу или школьное задание по информатике?

Ещё раз, для тех, кто в танке: если в стандарте не описано, что «должно быть переполнение стека», то может быть ВСЁ, ЧТО УГОДНО. А в стандарте этого не написано. И требовать от компилятора этого — по меньшей мере глупо.

emulek
()
Ответ на: комментарий от quest

должна быть опция которая будет отслеживать выделение стека и остановит процесс с более вменяемым сообщением

стек сам процессор выделяет, а не компилятор. Потому переполнение стека может К ЧЕМУ УГОДНО привести. Раньше и программы работали КАК УГОДНО, сейчас получше стало, есть ошибка страниц.

emulek
()
Ответ на: комментарий от emulek

лабу или школьное задание по информатике?

угу, как ты понял что я в 1 классе еще?

И требовать от компилятора этого — по меньшей мере глупо.

Это удобная опция которая должна включать дополнительный код отслеживающий увеличение стека.

Ты не поверишь но -fstack-protector-all -fstack-check -fsanitize=address -fsanitize=bounds в стандарте ТОЖЕ нет.

quest ★★★★
()
Ответ на: комментарий от emulek

стек сам процессор выделяет, а не компилятор.

процессор стек выделяет? круто.

интересно а что это такое:

subq $40000000, %rsp

Потому переполнение стека может К ЧЕМУ УГОДНО привести.

Хватит уже про undefined behavior мы не в детском саду

quest ★★★★
()
Ответ на: комментарий от quest

Ты не поверишь но -fstack-protector-all -fstack-check -fsanitize=address -fsanitize=bounds в стандарте ТОЖЕ нет.

и что?

процессор стек выделяет? круто.

вот знай.

интересно а что это такое: subq $40000000, %rsp

это ты из rsp вычитаешь 40000000

Хватит уже про undefined behavior мы не в детском саду

не все после д/с становятся говнокодерами.

emulek
()
Ответ на: комментарий от emulek

это ты из rsp вычитаешь 40000000

а нельзя ли тут вставить код который будет проверять можно вычитать или нет?

quest ★★★★
()

Используй хаскел,

anonymous
()
Ответ на: комментарий от quest

Лезть в TLS на каждом вызове функции? Ах, увольте.

vzzo ★★★
()

stopitplease, Eddy_Em, ziemin, quest, emulek

Чуваки, вы столько друг другу подоказывали, в том числе и мне, какое я нубло, но так никто и не сказал. Друзья, какая разница? В паскале один код работает, в сишке отказался работать. Оказалось, что разное поведение. В чём разница поведения?

Понимаю что прошу разжевать и в рот положить. Уж звиняйте что нет желания и сил читать книги по Си для Си, наглая моя харя. Узнать хотел бы, буду рад если для кого-то не принципиальна моя лень и глупость :)

Ну позяяяяязяя!!!

Deleted
()
Ответ на: комментарий от Deleted

Для простоты считай,что в паскале все массивы как static в C.

По крайней мере те, что в основном блоке.

Попробуй в своём паскале функцию с таким массивом замутить.

ziemin ★★
()
Последнее исправление: ziemin (всего исправлений: 1)
Ответ на: комментарий от Deleted

По-моему, уже сто раз сказали, что в C локальные объекты функции аллоцируются, в основном, на стеке. А в Паскале это, вероятно, статические данные

stopitplease
()
Ответ на: комментарий от Deleted

Короче, большие данные лучше аллоцировать с помощью malloc, а освобождать с помощью free. Или, как посоветовали выше, написать перед этим массивом «static».

stopitplease
()
Ответ на: комментарий от ziemin

Для простоты считай,что в паскале все массивы как static в C.

ок. а static размещает данные не в стек, а куда?

Попробуй в своём паскале функцию с таким массивом замутить.

попробовал, segfault) Классно, а как в паскале сделать чтоб работало? Ключевого слова нету. Интересно, значит данные что в функции помещаются в стек? :)

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.