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

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

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

не боишься что потратишь в 2 раза больше памяти на копию строки?

вот как сейчас стоит перед глазами несчастный, котрый по 2Гб в строки сохранял, а потом жаловался на stackoverflow что де память куда-то уходит быстро

привёл бы к усложнению обеспечения безопасности по исключениям

чому бы тогда вообще не запретить new? А то мало ли чего они там нагородят, противные :-)

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

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

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

Вот видишь, вместо того, что бы почитать хоть что нибудь по C++, ты занялся никому не нужным расследованием. :)

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

не боишься что потратишь в 2 раза больше памяти на копию строки?

1. QString хранит строки QChar, не конкретизируя кодировку этих QChar'ов. ТС хочет вывести строку в системной кодировке, как ты обойдёшься в общем случае без создания копии строки в нужной кодировке?

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

чому бы тогда вообще не запретить new? А то мало ли чего они там нагородят, противные :-)

Так вот в С++14 добавят std::make_unique и этот new будет нужен только для реализации классов непосредственно управляющих распределением памяти (умные указатели, векторы, списки и т.д.). Стиви, голым new не рекомендуют пользоваться уже дано, даже выражение типа foo(new A, new B) может привести к утечке памяти (при том что foo, удаляет полученные объекты или иным способом заботится об этом).

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

Такой да не такой. Проблема ТС решилась использованием метода в выражении. Как ты это объяснишь?

Наоборот, от этого у него проблема появилась (корни проблемы на самом деле более фундаментальные и выходят за технические рамки ЯП).

Т.к. время валидности указателя char*, который возвращает аксессор QByteArray::data(), привязано по очевидным причинам к времени жизни самого объекта QByteArra(), то проблема решилась продлением времени жизни самого QByteArra на весь блок ф-ии где использовался этот char:

{
    QByteArra plain =msg.toLocal8Bit();
    // ^^^ тут начинает жить объектъ вместе с plain.data() 

    fputs(plain, stderr);

    // vvv А тут закначивает жизнь plain и его plain.data()
}

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

не конкретизируя кодировку этих QChar'ов

а не UTF-16 ли?

ТС хочет вывести строку в системной кодировке

поменять системную кодировку на UTF-16

ой, для этого придется установить Windows. Вот жопа.

голым new не рекомендуют пользоваться уже дано

заметьте, это сказал настоящий крестопоклонник, а не крестохейтер :3

надо добавить в расстрельный список со ссылкой на цитату :3

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

что бы почитать хоть что нибудь по C++

Я почитаю C++. А ещё уважаю лисп.

Ты, похоже, мыслишь фортрановфми категориями...

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

// ^^^ тут начинает жить объектъ вместе с plain.data()
// vvv А тут закначивает жизнь plain и его plain.data()

А тебя не смущает то, что .data() ни разу не используется?

Что ты вообще собирался доказать этим огрызком кода?

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

Я почитаю C++. А ещё уважаю лисп.

Ну что молодец. Я так понимаю его ты тоже не знаешь, а порассуждать можешь? :)

Ты, похоже, мыслишь фортрановфми категориями...

Почему та делал такой вывод? Потому что фортран ты тоже не знаешь? :)

Тебе уже третью страницу пытаются разжевать про время жизни объектов, а ты третью страницу пишешь ерунду. Не надоело?

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

А тебя не смущает то, что .data() ни разу не используется?

Нет, ибо используется тут

fputs(plain, stderr);
В общем.. тебе, как и ТС, тоже не стоит никогда заниматься прогрммированием.

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

Палишсо. Слишком синхронно вы с анонимусом действуете.

По теме. Аргументы уже сожгли детектор, так что работаю без приборов.

fputs(plain, stderr);

И чё?

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

Напиши пожалуйста, что по твоему здесь происходит, что создается?

char *ptr = str.toLatin1().constData();

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

const char *message=msg.toLocal8Bit().data();

Выражение из метода "QByteArray Qstring::toLocal8Bit()" создает таки объект QByteArray. Вот если бы ты знал кресты (да даже не кресты, просто не был бы погромистом), то и знал бы что сей уничтожается сразу как отрабатывает выражение. А то на что ссылается указатель «char * QByteArray::data()» уничтожается вместе с объектом. (Тред до конца не читал, но я с вас офигиваю, друзья) Сие не поведение либы, сие не поведение компилятора, сие использование деструкторов класса по назначениею, это то из-за чего кресты могут жить без сборщиков мусора и не течь да не жрать при том тонны памяти на хеловорлд, но сие требует наличие головы на плечах и знаний у кодера.

И таки правильный код (Оно не делает лишних вызовов «QByteArray Qstring::toLocal8Bit()» - таки создание и передача объекта, да с тягой ТСа не самых легких. Не использует указателей на уничтоженные данные.):

QByteArray ba = msg.toLocal8Bit();
printf("Len of line: %d\n", ba.data().size());
fwrite(ba.data(), sizeof(char), ba.data().size(), stderr);

Читайте доки, книги (хотя бы Павловскую) и думайте мозгом, ну а если мозг гуманитарный выбирайте правильный вид деятельности. Удачи!

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

ОМГ. Речь шла о методе .data(), а ты предъявляешь какой-то левый метод. Если хочешь проверить моё понимание, то стоило привести цитату из мануала на этот метод.

Тоньше надо.

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

Не имеет значение, кто будет возвращать указатель: data или constData. Здесь проблема во временном объекте, создаваемым toLatin1. Чуть выше тебе еще раз пытались все разжевать. :)

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

Чуть выше тебе еще раз пытались все разжевать. :)

Ничего не путаешь? Как раз я и пытаюся разжевать про временные объекты.

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

Выше я уже отписываля, что мне не нравится, как назвали метод .data().

char * QByteArray::data()
Returns a pointer to the data stored in the byte array...

А мне вот нравится, метод таки даёт указатель на то пресловутое низкоуровневое «data», содержащееся в высокоуровневом объекте QByteArray. Оно таки есть поле в классе с объектом которого ты бадаешься. И оно ВНЕЗАПНО уничтожается вместе с объектом, это одна из первейших вещей которым учат при изучении классов (пишите деструктор и чистите в нём все поля, данные которых лежат в куче). Да сие скорее даже заповедь, одна из наипервейших, аки заповеди возлюби господа своего и ближнего своего в христианстве.

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

Я не сильно волоку в Qt, но даже так понимаю, что ты чего-то не понимаешь. О каком уничтожении идёт речь, если выхода из локальной области нет?

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

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

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

Палишсо. Слишком синхронно вы с анонимусом действуете.

Это просто в тебе просыпается способность всё без нужды переусложнять (~противоположность бритве Оккама) и искать несуществующие «скрытые» особенности и удивительные непонятные явления. Примерно как с char* и QByteArray() в этом треде. Или может быть даже ещё хуже, параноидальная шизофрения даёт о осебе знать.

И чё?

В чём вопрос то? Это тоже самое, что и

fputs((const char*)plain, stderr);
fputs(plain.data(), stderr);
const char *ptr = plain.data();

fputs(ptr, stderr);

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

К сожалению, так же как и C++. За это отвечает он. :)

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

Отвечу сразу всем (тем более, что мои подозрения ты не снял)

Воу-воу.

Исходя из своего понимания я уже решил задачу.

Вопрос на засыпку: как отличается объект, имеющий метод operator char * от char *?

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

Я не сильно волоку в Qt, но даже так понимаю, что ты чего-то не понимаешь. О каком уничтожении идёт речь, если выхода из локальной области нет?

Qt тут не причем. Ещё раз объясняю:
В выражении «const char *message=msg.toLocal8Bit().data();» ты методом «QByteArray Qstring::toLocal8Bit()» создаешь объект класса QByteArray. Сей персонаж живёт до тех пор пока выполняется выражение, сразу как выражение отработало объект уничтожается. Это элементарно, сие нужно знать. Дык вот а затыка у тебя происходит когда ты обращаешься к полю этого объекта, полученному посредством метода «char * QByteArray::data()». Т.к. сей метод отдаёт лишь указатель на содержащиеся в объекте класса QByteArray, указатель не действителен сразу по завершению выполнения сего выражения, вместе со смертью объекта QByteArray умирает и то на что ссылается указатель «char * QByteArray::data()». Объект получив поток выполнения в свой деструктор просто удаляет эти данные, т.к. они лежат в куче. А любой адекватный программист как отче наш знает, что деструктор должен чистить кучу, иначе прога потечёт. Проблема не в Qt и не в ЯП, проблема в образовании.

ЗЫ:

выхода из локальной области нет

Я тебе писал выше пример как правильно, вот там выхода из области нет, там я расположил пресловутый QByteArray на стеке и он живёт пока не стек не отмотнётся назад. Это элементарно.

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

В выражении «const char *message=msg.toLocal8Bit().data();» ты методом «QByteArray Qstring::toLocal8Bit()» создаешь объект класса QByteArray

Да ну? Может всё-таки char *?

Дык вот а затыка у тебя происходит когда ты обращаешься к полю этого объекта, полученному посредством метода «char * QByteArray::data()»

Ога.

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

Исходя из своего понимания я уже решил задачу.

Но ничему не научился, потом будет плохой фреймворк, ЯП, компилятор. «Все погромисты, один я д'Артаньян.»

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

Да ну? Может всё-таки char *?

Нет, нет, нет и ещё раз нет! «msg.toLocal8Bit()» создает объект класса QByteArray, далее «toLocal8Bit().data()» возвращает указатель на поле объекта QByteArray. По выполнению выражения QByteArray уничтожается, тк ты не расположил его ни в кучу ни на стек. Это же основы. Дык вот указатель на поле уничтоженного объекта не действителен.

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

У меня комменто-слепота. Все вокруг сыпят фактами (имеющими отношение к теме) и цитатами, а я, дурак, всё твержу одно.

Вот и ты пытаешься мне что-то объяснить. Попробуй прочитать документацию и объяснить мне своими словами, а? Может тогда мой страшный недуг отступит, на время.

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

Это же основы

Я аж (почти) прослезился! Куда пропали старые добрые области видимости, о которых я слышал в детстве?

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

Может ты сам попробуешь в этом разобраться? Это настолько простые вещи, что ждать своего героя, который все тебе разжует, глупо. ;)

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

У меня комменто-слепота. Все вокруг сыпят фактами (имеющими отношение к теме) и цитатами, а я, дурак, всё твержу одно.

Я тебе твержу элементарными терминами: «Стек, куча, выражение, класс, объект, поле, указатель»

объяснить мне своими словами, а?

Я не знаю чем тебе заменить эти определения, это базовые вещи, которые программист обязан знать. Действия либы и прочее я тебе объяснял и ссылкой на доки и своими словами.

Я аж (почти) прослезился! Куда пропали старые добрые области видимости, о которых я слышал в детстве?

Ты лучше усвой как следует что такое стек, куча и выражение (в котором могут быть временные объекты). Ты должен понимать что, если объект возвращенный из функции (не важно метод это класса или что-то ещё) не разместить в памяти (стек или куча), по завершении выражения пропадает.

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

Подойди с другой стороны. Я просто прав, а это вы со мной соревнуетесь (пока не впечатляюще, кстати)

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

Все вокруг сыпят фактами (имеющими отношение к теме) и цитатами, а я, дурак, всё твержу одно.

всё верно. Только «дурак» как-то мягко сказано

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

там я расположил пресловутый QByteArray на стеке и он живёт пока не стек не отмотнётся назад. Это элементарно.

Фак мой мосг.

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

Зачем проверять, если я и так знаю, что прав? Может в мелочах я и ошибаюсь (совсем маленькие мелочи), но всё работает. ТС подтвердил.

Пока ни одного правдоподобного варианта развития событий никто не предложил.

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

Аргументы (которых и так не было) кончились?

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

Вроде хорошо объяснил, но всё равно что-то не веритсо. Можно цитаты?

Какие тебе цитаты? Хочешь хоть чему-то научиться, прочитай для начала про память, Павловскую (Выражения стр37, Указатели стр51, Классы стр 178, Деструкторы стр188). Освой базовые вещи. Пока ты их не освоишь я тебе ничего не смогу объяснить, а если нужен учитель, то за полный курс крестов я возьму бабок.

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

Пока ни одного правдоподобного варианта развития событий никто не предложил.

Их уже написали множество, причем совершено разные люди. Ты просто не читаешь.

toLocal8Bit возвращает объект QByteArray, для которого вызывается метод data. Дальше компилятор считает, что этот временный объект никому не нужен и разрушает его. Результирующий указатель продолжает указывать на данные уже разрушенного объекта.

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