Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> "Какая угодна длина строки" (с) 
:(
    Опции темы
Compositum
Дата 1.6.2011, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(xvr @ 1.6.2011,  16:12)
Цитата(Compositum @  29.5.2011,  21:44 Найти цитируемый пост)
Из краткого сообщения, делаю предположение, что размер строки не может быть больше размера сегмента.

Неправильный вывод (пока оставим за бортом вопрос о существовании сегментов вообще). Твой массив расположен в стеке, вот именно он и переполнился. Сделай массив глобальным (объяви перед main)

Попробовал с глобальными...
Код

//Ритчи, урок 1.10, упр. 1.16
#include<stdio.h>
#include<limits.h>
char maxstring[ULONG_MAX];
//char maxstring[LONG_MAX];
//char maxstring[INT_MAX];

main(){        
    maxstring[0] = '\0';
    printf("Test...\n");
}

Результат
Цитата(Терминал)

bush@mycomp:~$ cd ./training/c/c89/ritchi/1/1.9
bush@mycomp:~/training/c/c89/ritchi/1/1.9$ gcc 1.16.c -o 1.16.out
1.16.c:5:6: error: size of array ‘maxstring’ is too large
bush@mycomp:~/training/c/c89/ritchi/1/1.9$

Код

//Ритчи, урок 1.10, упр. 1.16
#include<stdio.h>
#include<limits.h>
//char maxstring[ULONG_MAX];
char maxstring[LONG_MAX];
//char maxstring[INT_MAX];

main(){        
    maxstring[0] = '\0';
    printf("Test...\n");
}

Результат:
Цитата

bush@mycomp:~/training/c/c89/ritchi/1/1.9$ gcc 1.16.c -o 1.16.out
bush@mycomp:~/training/c/c89/ritchi/1/1.9$ ./1.16.out 
Убито
bush@mycomp:~/training/c/c89/ritchi/1/1.9$

Не понял... процесс был "убит" операционной системой? Если да, то почему?
Код

//Ритчи, урок 1.10, упр. 1.16
#include<stdio.h>
#include<limits.h>

//char maxstring[ULONG_MAX];
//char maxstring[LONG_MAX];
char maxstring[INT_MAX];

main(){        
    maxstring[0] = '\0';
    printf("Test...\n");
}

Результат:
Цитата

bush@mycomp:~/training/c/c89/ritchi/1/1.9$ gcc 1.16.c -o 1.16.out
bush@mycomp:~/training/c/c89/ritchi/1/1.9$ ./1.16.out 
Test...
bush@mycomp:~/training/c/c89/ritchi/1/1.9$ 

Как видим, в последнем случае откомпилировалось и отработало без ошибок, но на компиляцию ушло секунд 7... Почему в случае с локальной переменной это не сработало, а с глобальной - получилось?
PM   Вверх
xvr
Дата 1.6.2011, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(Compositum @  1.6.2011,  20:01 Найти цитируемый пост)
Почему в случае с локальной переменной это не сработало, а с глобальной - получилось? 

Локальная переменная располагается в стеке, а его размер ограничен. Глобальная - в обычной виртуальной памяти. Ее размер ограничен только доступной виртуальной памятью (кстати, на 64х битной машине размер виртуальной память меньше - 48 бит)
Так что long туда не влез (он занимает 63-64 бита адреса), а int влез (он занимает 31-32 бита)

Но учти, что система может иметь свои взгляды на размер памяти, и прибить процесс, который попытается реально обратится к слишком большому объему памяти. Когда кончится своп файл процесс получит sigfault

PM MAIL   Вверх
Compositum
Дата 1.6.2011, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

Репутация: нет
Всего: 1



Цитата(xvr @ 1.6.2011,  21:04)
Цитата(Compositum @  1.6.2011,  20:01 Найти цитируемый пост)
Почему в случае с локальной переменной это не сработало, а с глобальной - получилось? 

Локальная переменная располагается в стеке, а его размер ограничен. Глобальная - в обычной виртуальной памяти. Ее размер ограничен только доступной виртуальной памятью (кстати, на 64х битной машине размер виртуальной память меньше - 48 бит)
Так что long туда не влез (он занимает 63-64 бита адреса), а int влез (он занимает 31-32 бита)

Но учти, что система может иметь свои взгляды на размер памяти, и прибить процесс, который попытается реально обратится к слишком большому объему памяти. Когда кончится своп файл процесс получит sigfault

Спасибо за ответы. Ты пишешь, что размер стека ограничен, а чем обуславливаются размеры/ограничения стека? Я думал, что размер стека вычисляется компилятором на основе размеров переменных, используемых в программе. Я ошибся? 
Ещё я ведь могу объявить переменную как 
Код

static char maxstring[INT_MAX];

В этом случае она будет видна только в рамках этого си-файла - такая переменная так же будет размещаться в обычной виртуальной памяти или в стеке (компилируется и работает без сообщений об ошибке)? Насчёт размера виртуальной памяти не понял - ты имеешь в виду размер указателя на ячейку памяти?
Код

printf("sizeof(void *): %ld\n", sizeof(void *));

получаю: 8. Т.е. размер указателя - 64 бита.

Это сообщение отредактировал(а) Compositum - 1.6.2011, 21:26
PM   Вверх
bsa
Дата 2.6.2011, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Compositum @  1.6.2011,  21:21 Найти цитируемый пост)
Я думал, что размер стека вычисляется компилятором на основе размеров переменных, используемых в программе. Я ошибся? 
Да, ты ошибся. Компилятор может вычислить объем используемого стека только внутри одной функции. В некоторых простых случаях - в нескольких. Но он тебе со 100% гарантией не угадает, например, в случае использования рекурсии, глубина которой зависит от данных введенных пользователем. Поэтому, объемом стека заведует ОС.

Добавлено через 2 минуты и 51 секунду
Цитата(Compositum @  1.6.2011,  21:21 Найти цитируемый пост)
получаю: 8. Т.е. размер указателя - 64 бита.

ты не путай размер указателя и разрядность виртуальной памяти. У указателя много места занимает выравнивание, которое необходимо, чтобы процессор быстрее считывал из памяти (т.е. считывание 8 байт с адреса, выравненного по 8 (addr % 8 == 0) займет 1 машинную операцию, а считывание с невыравненного - 2).
PM   Вверх
xvr
Дата 2.6.2011, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(Compositum @  1.6.2011,  21:21 Найти цитируемый пост)
получаю: 8. Т.е. размер указателя - 64 бита.

Указатель действительно 64 бита, но могут быть нюансы. Например для x86 64х битной архитектуры обычно только младшие 48 битов (точное количество зависит от процессора) значимые. А оставшиеся старшие биты (64-48=16) должны совпадать друг с другом и с последним значащим битом (47м). В противном случае при попытке что либо прочесть/записать по такому указателю получите ошибку сегментации.
Т.е. виртуальное адресное пространство действительно 64х битное, но в его середине есть дыра весьма приличного размера  smile 


PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0471 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.