LINUX.ORG.RU

C, C++. Какова максимальная длина сишных строк (сегфолт на строке длиной ~640 Кб, GCC)?


0

4

Сейчас словил сегфолт при выводе строки длиной 636180 байт.

Сегфолтная команда:

fprintf(stderr, "%s", message);

где message имеет тип «const char *message» и размер данных в 636180 байт.

В стеке вызовов видно, что после функции fprintf() были вызваны:

strlen ()	
__GI__IO_fputs (str=0xb2379018 <Address 0xb2379018 out of bounds>, fp=0xb6ecc960 <_IO_2_1_stderr_>)

- т. е. сначала fputs(), последней strlen().

Сегфолт в дебрях strlen(). (Мне не нравится и строка с fputs(), ибо в ней «Address 0xb2379018 out of bounds»).

Таких проблем на коротких строках (чуть более 1000 знаков) не возникает.

Вопрос: существуют какие-то ограничения в компиляторах на работу с сишными строками? Я то думал, что размер строки ограничивается максимальным числом unsigned int. А тут вона как - 630 КБ прожевать не может.

Или, к примеру, существует какое-то ограничение на работу с потоком ошибок, только я о нем не знаю?

Если это важно: gcc (Debian 4.7.1-7) 4.7.1

★★★★★

Самое главное покажи — как и где выделил память под строку. Сам где-то с памятью намудрил, а виноват Путин

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

Самое главное покажи — как и где выделил память под строку. Сам где-то с памятью намудрил, а виноват Путин

http://qt-project.org/doc/qt-4.8/qbytearray.html#data

The pointer remains valid as long as the byte array isn't reallocated or destroyed.

Перевод:

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

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

Дело в string.data()

В QByteArray.data(), если быть точным.

toLocal8Bit() возвращает QByteArray.

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

The pointer can be used to access and modify the bytes that compose the array

modify the bytes

Сильно сомневаюсь. Проверь, можно ли его использовать в выражении типа

somestring.data()[1] = '1';

Проверка должна состоять в том, что в исходной строке второй символ должен поменяться на '1'. Конечно может и так быть. Но, вообще-то это необязательно. ИМХО это или ошибка в документации или Qt ещё лютее чем stl

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

Если это временный объект, то он будет уничтожен в конце выражения. Врядли перед уничтожением он ещё один экземпляр создаёт, потом побайтово сравнивает и, если разница отправляет сигнал родительскому объекту.

UDP: Напомню - речь идёт об объёмах данных порядка 640к

UPD2: Хотя, конечно они могли переопределить операцию присваивания индексу.

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

Если это временный объект, то он будет уничтожен в конце выражения. В

Что именно временный объект, сам QByteArray() или что data() возвращает?

если разница отправляет сигнал родительскому объекту.

аналогично, что ородительский объект, QByteArray или что-то другое?

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

Что именно временный объект, сам QByteArray() или что data() возвращает?

что ородительский объект, QByteArray или что-то другое?

Сам-то как думаешь? Вообще я в кутях не особо волоку. Просто изучил подобное поведение на stl.

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

Сам-то как думаешь?

Честно говоря вообще без понятия как ты это себе представляешь в деталях, потому спросил. Видно пока что как-то неправильно.

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

В общем объясню как я это понимаю.

Начнём с самого простого. Если компилятор видит, что значение больше не используется, то он уничтожает объект.

Обычно это означает, что он освобождает память (это ещё со времён C пошло).

Однако в C++ он ещё и вызывает деструктор (это я рассуждаю на уровне «пользователя» библиотеки, например, stl).

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

В C++, к сожалению это не так. Если библиотека рулит распределением памяти или сложно устроена, а вместо обычного указателя char * возвращает указатель на объект, который способен преобразовываться в char *... В общем там не совсем настоящий указатель на char* а объект неизвествного класса, у которого есть operator char *.

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

компилятор видит, что значение больше не используется, то он уничтожает объект.

Эм... Как _компилятор_ это увидит в рантайме?

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

Я склоняюсь к мысле, что таки ограничение stderr.

На скорую руку написанный тест опровергает эту мысль.

#define MESSAGE_SIZE 1024*1024*1024

int main(int argc, char** argv)
{
  char* message = calloc(1, MESSAGE_SIZE);
  
  for(int i = 0; i < MESSAGE_SIZE; ++i)
    {
      message[i] = i%254 + 1;
    }

  fprintf(stderr, "%s", message);

  free(message);

  return 0;
}
Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Xintrea

В C/C++ рантайм это связывание динамических библиотек. Компилятор...

Тьфу ты. Хотел выразить мысль, а написал другое. В любом случае тебе пригодится.

А мысль, которую я хотел выразить в том, что в отличии от скриптовых языков в C/C++ «статическая» типизация. Статичность тут в том, что просто так строку в число в рантайм не превратишь.

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

Ты хотел сказать «Никогда больше не программируй на C/C++». Я это знаю.

Нет, никогда больше ни на чем не программируй. Будто при написании кода на другом языке ты внезапно перестанешь быть быдлокодером.

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

Уже разобрались. stderr тут не причем. Он сжирает ~640Кб легко.

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

Программировать можно и не на языке, быдлятина.

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

Нет, я имел в виду вообще не программируй. Без английского языка тебе и соваться туда нельзя.

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

Без английского языка тебе и соваться туда нельзя.

У тебя какое-то узкое представление о программировании. У нас в СССР и без онглийского обходились.

А вот тут тебе совсем пополохеет:

http://www.1c.ru/rus/products/1c/predpr/compat/soft/demand.htm?printversion=y

Тексты модулей конфигурации должны быть удобочитаемыми и понятными:
- все переменные и вызовы процедур, функций, методов должны быть на русском языке

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

У нас в СССР и без онглийского обходились.

И где теперь ваше СССР?

1C

Как это поделие для бухгалтеров связано с программированием?

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

У нас в СССР и без онглийского обходились.

И где теперь ваше СССР?

В наших сердцах, епт.

Как это поделие для бухгалтеров связано с программированием?

Я даже не знаю что ответить. Представь, оно работает в компьютере. Его кто-то запрограммировал и оно работает. Выполняет свои функции, в отличие от тебя. Как-то так.

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

В C++, к сожалению это не так. Если библиотека рулит распределением памяти или сложно устроена, а вместо обычного указателя char * возвращает указатель на объект, который способен преобразовываться в char *... В общем там не совсем настоящий указатель на char* а объект неизвествного класса, у которого есть operator char *.

Что-то тебя понесло куда-то.

Проблема была лишь в том, что возвращали указатель на внутренние данные временного объекта, который убивался после вычисления выражения. А указатель (адрес), указывающий уже во тьму, оставался.

yoghurt ★★★★★
()

у вас скорее всего переполнение стека....

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

В общем там не совсем настоящий указатель на char*

Совсем настоящий, других не бывает. QByteArray() такой же std::string(), т.е. упрощённо адрес на кусок памяти и её размер. Только один позволяет этот кусок редактировать прямо через char*, а другой нет.

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

Совсем настоящий, других не бывает...

А вот и нет, а вот и нет! Здесь прослеживается наследие C. Дело в том, что в C++ есть операторы. И они могут возвращать объекты. У которых, в свою очередь есть операторы. Ну и т.д.

Смысл в том что C даёт небывалую свободу действий. До определённого момента стандарты C++ ограничивали полёт фантазии Страуструпа. И только сейчас они, понемножку, впмсывают в него библиотеки.

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

У тебя какое-то узкое представление о программировании. У нас в СССР и без онглийского обходились.

В СССР было издательство «Мир», которое переводило все основные тексты. И где оно теперь?

А вообще, ты гандон. Уходи отсюда.

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

Нет, я имел в виду вообще не программируй.

Во. Топик помечен как решённый и только на второй странице я нашёл решение проблемы. Удивительно, это тупое жывотное Xintrea вроде бы довольно долго обитает на техническом форуме, но так и не обрело никакого представления о том, что конпелятор не будет держать в памяти какой-то там QByteArray после того как тот стал ненужен программе. Ну и все ссылки на данные этого объекта авно протухли к моменту их использования. Если человек после стольких лет смотрения в компьютер не может этого понять, то ему действительно лучше не пытаться программировать.

Вообще так посмотреть на нынешнюю молодёжь - вообще стыдно становится. Вот например замечательный русский поэт Пушкин в 33 уже успел стать нашим всем и погибнуть на дуэли. А ради чего живёт это быдло?

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

Будет, но после выхода из функции bar, GC уничтожит объект, на который ссылалась f. В С++ такой код типичен при создании немодальных диалогов, в питоне надо явно хранить ссылку на это диалоговое окно, иначе окно будет создано, показано и тут же уничтожено.

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

Да нет же. Язык тут не причём. Никакой компилятор не уничтожит переменную, зная, что она используется.

А при чём тут переменные? Речь шла о временных объектах. А время жизни объектов и порядок их создания и разрушения - это всё определяется языком, а не библиотекой. Более того, наличие деструкторов, объектов на стеке (как связанных с переменными, так и временных) и детерминированный порядок вызова деструкторов позволяет реализовать на С++ классы определяющие политику владения ресурса. Голый указатель в современном С++ - это либо невладеющий указатель, либо использующийся для работы с С-шной библиотекой (своеобразный FFI). Второй случай стилистически допустим только, если использование С-шной библиотеки хорошо локализовано.

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

Проверка должна состоять в том, что в исходной строке второй символ должен поменяться на '1'. Конечно может и так быть. Но, вообще-то это необязательно. ИМХО это или ошибка в документации или Qt ещё лютее чем stl

Речь идёт о QByteArray::data, исходная строка тут уже ни при чём.

Begemoth ★★★★★
()

Полный код давай.

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

А вот и нет, а вот и нет! Здесь прослеживается наследие C. Дело в том, что в C++ есть операторы. И они могут возвращать объекты. У которых, в свою очередь есть операторы. Ну и т.д.

Простых типов это не касатеся, в частности char*. Они все обратно совместимы с C и поменять их поведение нельзя.

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

Достаточно прочитать документацию и исходники Qt.

и исходники Qt

«ушел читать, встретимся через 6 лет»

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

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

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

особенно если вспомнить, что ТС там где-то писал про запуск куте на андроид-девайсе, иначе нахрена бы ему непонятные обертки над qDebug проксирующие строки, и у него баттхерт уже от того что всё «просто неработает». Какой тут в жопу стандарт, когда «всё просто неработает» и ты как инвалид даже не можешь глянуть дебагер чтобы понять почему

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

Рано или поздно ТС научится отличать библиотеки от языка

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

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

QString уникодная строка, toLocal8Bit возвращает QByteArray, содержащий строку переконвертированную к локальной 8-битной кодировке — естественно это копия строки, а не сама строка!

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

Разработчики пошли вторым путём чтобы избежать колоссальных утечек памяти.

А нельзя отнаследовать строку и поправить в наследнике это досадное решение?

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

Какой тут в жопу стандарт, когда «всё просто неработает» и ты как инвалид даже не можешь глянуть дебагер чтобы понять почему

Чтобы _понять_ почему не работает - нужен мозг, а не отладчик.

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

А нельзя отнаследовать строку и поправить в наследнике это досадное решение?

Там и так всё нормально и «правильно» сделано.

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

Чтобы данные не удалялись. Специально конкретно для этого случая. А «этот случай» был бы четко виден использованием не QString а чего-то другого, какого-нибудь QPersistentString

Нельзя - QString::toLocal8Bit - не виртуальная функция.

вот она вся суть ООП. «Не виртуальная функция» читаем как «нужно скопипастить». Ехал копипаст через копипаст, а потом версия фреймворка апнулась и всё развалилось

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

Выходит, можно. На самом деле я не помню, как это сделано в stl, и, пожалуйста, не отправляй меня в этот ад опять.

Суть в том, что объект может конвертировать себя в любой (тем более штатный) тип. И в stl (а, походу и в qt) этим злоотребляют.

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

Чтобы данные не удалялись

А как? Сборки мусора в С++ нет, возврат голого указателя на объект на куче привёл бы к усложнению обеспечения безопасности по исключениям и в случае ТС - к утечке памяти.

Специально конкретно для этого случая

этот случай нормально записывается так:

auto bytes = str.toLocal8Bit();
fwrite(bytes, 1, bytes.size(), stderr);
Begemoth ★★★★★
()
Ответ на: комментарий от ziemin

И в stl (а, походу и в qt) этим злоотребляют.

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

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

И ты, Брут!

Не полезу я в ихние доки. Для обычного пользователя я, хоть и примитивно, но пояснил.

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

Выходит, можно. На самом деле я не помню, как это сделано в stl, и, пожалуйста, не отправляй меня в этот ад опять.

А куда тебя отослать? Ты же фантазируешь и бред несёшь не понятно на чём осноывая свои выводы.

Суть в том, что объект может конвертировать себя в любой (тем более штатный) тип. И в stl (а, походу и в qt) этим злоотребляют.

Такой сути нет, char* это не объект. QByteArray() упрощённо (если не вдаваться в детали CoW) состоит из указателя на кусок памяти в виде char* и его длины в виде целого числа. Метод data() в данном случае это просто аксессор к этому указателю.

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

Это тоже самое, что и data(), т.е. аксессор в виде сахара. Не нужно никуда лазить, достаточно понять, что char* точно такой же char* как и в си.

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