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)
Ответ на: комментарий от stopitplease

Короче, большие данные лучше аллоцировать с помощью malloc, а освобождать с помощью free

это как понял динамическая память? Это решение для больших данных внутри функций?

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

Я сказал тебе, как сделать. Что-то там проверять в уже откомпилированном коде - это бред

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

Оказалось, что разное поведение. В чём разница поведения?

Есть память на стеке (локальные переменные как у тебя) и есть память в куче (malloc, new).

malloc и new можно контролировать внутри программы, память на стеке нет и это вызывает неопределенное поведение.

я же за то чтобы была опция которая в режиме отладки (пусть и ценой большой потери производительности) поможет отследить это.

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

Это решение для больших данных внутри функций?

Да. И кроме того, пока не сделаешь free, данные никуда не уйдут, т.е. ты можешь передать их куда либо или вернуть из функции

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

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

Отдельная область. Причём она считается на этапе компиляции, так что переполнена быть не может.

попробовал, segfault)

Собственно тогда понятно твоё недоумение в топике. В паскале основной блок это основной блок. В C такого нет и main такая же функция, как и все остальные.

Классно, а как в паскале сделать чтоб работало? Ключевого слова нету.

Заводи глобально. Или через динамическую память.

Интересно, значит данные что в функции помещаются в стек? :)

Да, аргументы и локальные переменные. Кроме тех, под которые ты выделишь память сам. Поэтому не рекомендуется передавать в аргументах функции массивы в языках, которые это позволяют и всякого рода структуры.

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

Во времена универа, у меня одногруппник решал задачу о 8 ферзях в размерности доски n x n, где n было довольно большое. Пытался делать в лоб перебором, но вот беда, для выделения памяти (он на С писал) ее (этой самой памяти) не хватало. Пытался одлжить у меня одну планку, чтобы посчитать.

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

В C такого нет и main такая же функция, как и все остальные.

Хотя, если уж копать... Основной блок в C есть. И он как раз включает в себя main.

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

И что? «Это» место не становится от этого блоком

Отчего же? Файлы состоят из блоков.

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

Спасибо тебе, и остальным. Вдуплил. Как понял паскаль требует строгой последовательности объявления, а Си позволяет декларировать в разных местах программы. Если не трудно, скажи про extern.

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

а Си позволяет декларировать в разных местах программы ключевым словом static.

fix. еще говорят что паскаль многословный :) еще б понять о extern, register и auto. ))

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

Если не трудно, скажи про extern.

Ну если формальное описание тебя не устраивает...

Будем говорить о функциях, как о самом сложном случае. Для лучшего понимания нужно думать как компилятор.

Что для него функция? Имя + Аргументы + Тело. Причём тело необходимо на этапах линковки и исполнения. Для проверки синтаксиса и генерации вызова компилятору необходимо и достаточно имени и аргументов, а тело нафиг не нужно.

Соответственно extern задаёт имя и (в большинстве случаев) аргументы.

Именно поэтому ошибки отсутствующих функций выдаёт линкер: компилятор даже не проверяет есть ли такая функция на самом деле или нет! Ему хватает имени.

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

Как понял паскаль требует строгой последовательности объявления, а Си позволяет декларировать в разных местах программы.

И,кстати, ты не совсем правильно понял. Суть в том, что в паскале основной блок выделен, а в C нет.

И там и там функции крашатся из-за переполнения стека.

И там и там глобальные переменные статические.

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

malloc и new

понял про стек, статическую и динамическую память. malloc и new для выделения динамической памяти? Почему два ключевых слова? у них тоже разное поведение? быстрый гугл сказал что new - c++, malloc - c. это так?

P.S. если не трудно, помоги с extern, auto, register. с любым из этих. лучше одним, что лучше дойдёт до меня :) Хочу понять в чём их смысл, и эквивалент паскаля.

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

Да. Только имя остаётся локальным, так что можешь во всех своих функциях завести переменную "a" и они будут разными и конфликтовать не будут.

Я как-то интересовался - им генерится какое-то псевдослучайное имя.

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

Ну если формальное описание тебя не устраивает...

я не совсем это понимаю)) глобальные переменные и функции я например в паскале объявляю в модуле:

unit
    exunit;

interface
    var
        unitx : integer = 1337;
        unity : real;

    procedure helloworld;

implementation

    procedure helloworld;
    begin
        writeln('Hello world');
    end;

end.
потом импортирую в нужный блок.
program ex1;
uses
    exunit;
var
    unitx : integer = 4000;
    unity : real = 1.0;

procedure helloworld;
begin
    writeln('die world');
end;

procedure myproc;
var
    unitx : integer = 22;
begin
    writeln('0: ', unitx);        // 22
    writeln('1: ', ex1.unitx);    // 4000
    writeln('2: ', exunit.unitx); // 1337
end;

begin
    writeln(exunit.unitx); // 1337
    writeln(unity);        // 1.0
    helloworld;            // die world
    exunit.helloworld;     // hello world
    myproc;
end.
по какой аналогии мне понять extern? как его вообще использовать? :)

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

static в отличие от объявления переменной за main определяет её область видимости только в main? а как в другой функции использовать эту статическую переменную?

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

В паскале все переменные и процедуры в блоке interface являются как extern в C, только аргументы указывать обязательно.

И кстати это не глобальные, а экспортируемые. ЕМНИП перекрывать их можно.

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

как сделать на Си, аналогично тому, что было в паскале? Друг, помоги если можешь. Библиотек немало, хочу знать как переписать.

Deleted
()
Ответ на: комментарий от Deleted
  • Юниты делишь на две части.
    • Всё, что в interface пихаешь в .h с префиксом extern;
    • Всё, что в implementation пихаешь в .c;
  • Соответственно, вместо uses делаешь #include<.h>
  • Т.к. блоков инициализации модулей в C нет, превращаешь их в функцию типа ${NAME}_init(). И обязательно вызываешь её перед использованием любых компонентов бывшего паскалевского модуля.
  • Все типы, естественно, приводишь;
  • ...

Может я ещё чего забыл... Последний раз трогал паскаль 11 лет назад в техникуме.

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

Кстате! Если у тебя реально библиотеки, то проще их компильнуть и использовать в C! Прям как библиотеки (.so).

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

хух, понял. а зачем такое может понадобиться? ведь всёравно генерится псевдослучайное имя за пределами функции main, которую к тому же нельзя использовать в других функциях. Почему сразу не объявлять за main'ом? а если не хочешь использовать в функции эту переменную - не используй. Зачем потребовался static?

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

Что-то я всё про C, да про C... А речь то о плюсах!

Сделай из этих своих модулей объекты! Инициализацию запихни в конструктор. Подпрограммы это методы. Переменные это члены класса. Которые в interface, те в public. которые в implementation те в private.

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

Зачем потребовался static?

Чтобы реализовать модель «переменную видно только в блоке объявления и вложенных». Псевдоимена выглядят как «__sdjfgjs?sdfsdfjhg#12521376» и их ты никак не используешь напрямую.

а если не хочешь использовать в функции эту переменную - не используй

Эта модель строгая. Вольностей программисту не положено.

В смысле выбора тебе никто не даёт.

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

На самом деле паскаль делает похоже. Не считая того, что аналога static я там не припомню.

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

ничего не понял. сделал три файлика: myunit.h

extern int    unitx = 1337;
extern double unity;
myunit.c
helloworld() {
    puts("Hello world");
}
ex1.c
#include <stdio.h>
#include "myunit.h"

main() {
    int unitx = 4000;
    printf("%d\n", unitx);
    helloworld();
}
а как работать с другой unitx? с той что 1337?

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

Что-то я всё про C, да про C... А речь то о плюсах!

не-не! :-D я использовал тег сpp потому что литеру «с» нельзя использовать в качестве тега.

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

а заодно как helloworld сделать в файле свою, и потом использовать то импортированную функцию, то локальную.

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

понял про стек, статическую и динамическую память. malloc и new для выделения динамической памяти? Почему два ключевых слова? у них тоже разное поведение? быстрый гугл сказал что new - c++, malloc - c. это так?

malloc просто выделяет блок
new выделяет блок, если не получилось - кидает исключение (которое можно выключить), если получилось - вызывает конструктор или множество конструкторов.

malloc/free - C, C++ new/new[]/delete/delete[] - C++

P.S. если не трудно, помоги с extern, auto, register. с любым из этих. лучше одним, что лучше дойдёт до меня :) Хочу понять в чём их смысл, и эквивалент паскаля.

extern ключевое слово используемое в хедере чтобы объяснить компилятору что пусть сейчас переменной/функции еще и нету, но на этапе линковки оно появится

auto устаревший модификатор появившийся опять в последнем стандарте C++ - для тех кому лень писать нормальные итераторы при проходе по контейнерам

register так же как inline - устаревшие модификаторы подсказывающие компилятору как оптимизировать

не помню точно, но возможно register важен при использовании asm внутри исходника.

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

у меня исходники на паскале, и в разных реализациях паскаля компилируются юниты то tpu, то ppu, то еще какие-то, хотя я использую только две версии компилятора (borland, freepascal).

Deleted
()

«керниган ритчи язык программирования си» - набери в гугле - первая ссылка - открывается PDF - читай не хочу.

потом уже C++, пока C++ рано

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

обязательно, видимо придётся в виду того что перешёл на unix-like окружение, а тут почти весь софт на Си. сделаю это летом, когда будет больше свободного времени. Сейчас хотел узнать быстрее из прямых уст, как уже начать потихоньку переписывать с паскаля на си. Правда, вижу что нюансов тут - кукуево, а практическую ценность, почему это реализуется именно так - я не понимаю. Надеюсь в книгах это будет объясняться))

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

Пойми: язык С является языком высокого уровня, но и порог вхождения там высок! Ты не можешь просто взять и понадеяться на менеджер памяти С, потому что его там нет! Ты сам обязан выделить нужное количество памяти при помощи alloc и удалить потом ненужное при помощи free. И это хорошо, ибо можно писать очень хорошие программы, которые не текут, не жрут бешеное количество памяти и работают быстро. На жабке-пхытоне-сидиезе и прочем говне так не сделать.

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

а как работать с другой unitx? с той что 1337?

Очевидно #include «myunit.h»

Кстати! У #include аргументы различаются. Если в кавычках, то он ищет от текущего каталога. Если в <> он ищет в системных.

А так - тупо меняй uses на #include "".

И ещё один момент. Паскаль это делает автоматом, а C нет: оформляй .h файлы вот так:

#ifndef _H_$NAME
#define _H_$NAME
... Здесь код
#endif

Вместо имени подставляй имя файла без расширения. Это предотвратит повторуню загрузку.

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

Пойми: язык С является языком высокого уровня, но и порог вхождения там высок! Ты не можешь просто взять и понадеяться на менеджер памяти С, потому что его там нет! Ты сам обязан выделить нужное количество памяти при помощи alloc и удалить потом ненужное при помощи free. И это хорошо, ибо можно писать очень хорошие программы, которые не текут, не жрут бешеное количество памяти и работают быстро. На жабке-пхытоне-сидиезе и прочем говне так не сделать.

Прям готовая паста :)

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

Очевидно #include «myunit.h»

я так и сделал: #include «myunit.h». и загрузил за main'ом переменную unitx с значением 1337. А потом в main'e определил переменную unitx с значением 4000. Как в main'e использовать переменную unitx с значением 1337?

#ifndef _H_$NAME
#define _H_$NAME
... Здесь код
#endif

А что это и зачем? какую повторную загрузку? погоди. давай вначале с областью видимости подключаемых переменных. Как использовать в одном блоке импортированную переменную и локальную с одним именем?

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

Только за большие бапки

я б тебе и за этот комментарий доплатил, друг, если б мог.

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