Имя пользователя:
Пароль:
 | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Строки в С\С++

Ответить
Настройки темы
Строки в С\С++

Новый участник


Сообщения: 39
Благодарности: 0

Профиль | Отправить PM | Цитировать


При программировании строк в Visual C++ и под Linux я заметил такую штуку:
Если обявить строку как
char* pch = "Some_string" то операция
*pch = 'A' приводит к ошибкам выполнения. В Linux пишет Segmentation Fail т.е. ошибка обращения к памяти. И в тоже время объявление
char pch[] = "Some_string"
и операция
*pch = 'A' отрабатывает нормально без всяких глюков. Может кто знает где здесь собака зарыта. Только если можно поподробнее. Я думаю это как-то связано с защитой памяти в ОС или что-то в этом духе

Отправлено: 23:13, 05-04-2003

 

Старожил


Сообщения: 163
Благодарности: 0

Профиль | Отправить PM | Цитировать


Раз вы так все хорошо со строками ориентируетесь, то объясните такую вещь:
Visual C++
С помощью CListCtrl создаю свой собственный класс списка (использую пример, естественно), где каждый элемент списка представляет собой кнопку. Для отрисовки строк используется процедура
Код: Выделить весь код
DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
...
dc.DrawTedxt((LPCTSTR)lpDrawItemStruct->itemData,rect,
 * *DT_LEFT | DT_WORKBREAK);
dc.Detach();
}
//Строки добавляем сюда

m_List.AddString(_T("Some String"));
но если строки добавлять не константы, а так
CString str="Some String";
m_List.AddString(str); *
на экране галиматья,
т.е. любое использование локальных для данной процедуры переменных приводит к тому, что данные не отображаются.
если использовать
char str=new char[20];
...
то все отображается, но при попытке
delete str[] все накрывается, потому что список использует эти значения
Итог такой работает только если самостоятельно плодить утечку памяти, где ж это все хранится?

сама функция DrawItem использует не адрес а число, адрес содержащее, и в чем загвоздка не пойму


[s]Исправлено: Crew, 23:14 7-04-2003[/s]

-------
"Сколь бы сложной ни казалась проблема на первый взгляд, она, если правильно к ней подойти, окажется еще более сложной" - Пол Андерсон


Отправлено: 23:12, 07-04-2003 | #11



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

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


Новый участник


Сообщения: 39
Благодарности: 0

Профиль | Отправить PM | Цитировать


Crew
> Или вопрос был где именно хранится значение переменной?
Да вопрос как раз в этом то и заключался, то что будут ошибки так это я сам знаю. Почему?

ruslandh
А что по вашему должна делать команда
*pch='A' ? - записать по адресу, указанному в pch значение 'A' ? Т.е по адресу 0x00129 записать 0x100 ?
Фишка в том что *pch - разименование указателя. Т.е. 'A' будет записано в ячейку, адрес которой содержится в pch.
Vaulter
Так если объявление char* pch = "Some_String"; не выделяет память то куда же она будет записана. Ведь вывести я ее могу?


Отправлено: 14:32, 08-04-2003 | #12


Пользователь


Сообщения: 65
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


VBMUSTDIE
освободить то ее надо потом )
хотя это будут Memory leaks

Отправлено: 22:23, 08-04-2003 | #13


Новый участник


Сообщения: 39
Благодарности: 0

Профиль | Отправить PM | Цитировать


Знаете в чем еще фишка. Если сделать Active Confoguration не Debug а Release все работает. Вообще какая-то фигня

Отправлено: 23:09, 08-04-2003 | #14


Пользователь


Сообщения: 65
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


VBMUSTDIE
в Debug режиме, VC запускает прогу в своей куче.

Отправлено: 02:01, 09-04-2003 | #15


Модер


Сообщения: 1716
Благодарности: 17

Профиль | Сайт | Отправить PM | Цитировать


Crew
Меня очень ломает разбираться в MFC, потому давайте вместе.

Какие прототипы есть у вызова AddString? То есть, что можно передать этой функции (без учета приведения типа непосредственно внутри скобочек)?

Есть мысль, что AddString просто берет указатель на строку, если у тебя строчка в сегменте данных, то работать будет, если через CString - то ты отдаешь в лист указатель на CString-овую строку - при прибитии его тебе программа вполне обосновано дает по рукам, так как адрес, сохраненный в твоем листе, уже толком никуда не указывает. Аналогично и с массивом, пока не убьешь его, все будет работать.

Vaulter
Цитата:
в Debug режиме, VC запускает прогу в своей куче
Не понял нифига.

Я собрал проект как Debug.
Закрыл к чертям MSVC.
Запустил собранный проект.
Откуда он возьмет кучу MSVC?

-------
Васкецов Сергей
http://registry.oszone.net


Отправлено: 02:40, 09-04-2003 | #16


Аватара для shurikan

Старожил


Сообщения: 240
Благодарности: 1

Профиль | Отправить PM | Цитировать


Vaulter
Когда я выше упоминал, что к выделению памяти этот случай не имеет отношения, я имел ввиду динамическое выделение памяти. Слово "динамическое" я опустил, за что справедливо получил по шапке от vasketsov-а. Так вот, если память выделяется динамически с помощью всяких там new, malloc и им подобных, то память нужно освобождать, а если (как написано)
Код: Выделить весь код
char *pch = "Some string";
, то за это отвечает компилятор и об освобождении беспокоиться не нужно.

-------
UNIX, UNAS и др. Myself I'll like 'em


Отправлено: 12:51, 09-04-2003 | #17


Пользователь


Сообщения: 65
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


VBMUSTDIE

скажу всетаки секрет один:
char* a="something"; "а" вообще то будет распознана компилятором как строковая константа:
const char a[9]; поэтому и нельзя a[4]='a';

а вот
char a[]="something"; можно. потому как будет "а" будет как
char a[9];

Отправлено: 14:13, 09-04-2003 | #18


Старожил


Сообщения: 163
Благодарности: 0

Профиль | Отправить PM | Цитировать


vasketsov
AddString может принимать как CString, так и char *
функция прорисовки в любом случае получает только DWORD, вытаскивать что там такое моя задача (несложная) Я трейсером смотрел все она передает, но только почему-то (трейсер не улавливает) перерисовывает эти данные не один раз а три.
Но ладно бы так как я делаю, но я удалить не могу эти строки (которые создаю), иначе на экран выводится
"ЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭЭ"
причем удалить не могу ни до, ни после отрисовки, потому-что она еще раз вызывается. и если я удаляю после AddString, оно понятно почему накрывается.
А если в DrawItem(...)

Код: Выделить весь код
 * *const char*s=_T(LPCTSTR(lpDrawItemStruct->itemData));
 * *dc.DrawText(s), rect, 
 * *DT_LEFT | DT_WORDBREAK);
 * *dc.Detach();
 * *delete s[];
Одно из последних "извращений" приводящих к краху
Vaulter
Цитирую из книги "Программирование на VC++ 6.0" серия для профессионалов
Чтобы константы гарантированно хранились вместе с программой, придется немного поработать. Во превых, обратите внимание на строковые константы, которыми часто изобилуют программы. Может, Вы решили, что они будут данными "только для чтения"? Тогда попробуйте угадать еще раз. Действительно, поскольку Вы имеете право написать что-нибудь вроде
Код: Выделить весь код
char *pch ="test";
*pch='x';
"test" не может быть константой. Чтобы строка стала константой, ее надо соответствующим образом *объявить и инициализировать, например, так:

Код: Выделить весь код
const char g_pch[]="test";
Теперь g_pch хранится вместе с кодом. Но где именно?Чтобы ответить на этот вопрос, надо знать о секциях данных (data session), генерируемых компоновщиком Visual С++.
...
Имя * * *Тип * * * * * Доступ * * * * * * * * * * Содержимое
.text * * код * * * * * *только чтение * * * * *код программы
.rdata * данные * * только чтение * * * * *инициализированные константы
.data * *данные * * *чтение и запись * * *инициализированные данные (не кон)
.bss * * данные * * * чтение и запись * * неинициализ данные (не кон)

Секция .rdata - часть EXE файла, именно сюда компоновщик поместит переменную g_pch.

Из всего вышесказанного становится непонятно почему не работает код, ставшей причиной этого топика


[s]Исправлено: Crew, 0:04 10-04-2003[/s]

-------
"Сколь бы сложной ни казалась проблема на первый взгляд, она, если правильно к ней подойти, окажется еще более сложной" - Пол Андерсон


Отправлено: 23:51, 09-04-2003 | #19


Модер


Сообщения: 1716
Благодарности: 17

Профиль | Сайт | Отправить PM | Цитировать


Цитата:
Из всего вышесказанного становится непонятно почему не работает код, ставшей причиной этого топика
Потому что это лажа.

Пример 1.
Цитата:
char *pch ="test"; *pch='x';
"test" не может быть константой.
В C/C++ константность - свойство не данных, а переменных. Две переменные, одна константная, другая нет, могут ссылаться на одно и то же "test", это никак взаимно не ограничивает операции с ними. Потому речь о константности "test" вести абсолютно бессмысленно.

Пример 2.
Цитата:
const char g_pch[]="test";
Секция .rdata - часть EXE файла, именно сюда компоновщик поместит переменную g_pch
Опаньки!
Код: Выделить весь код
void x(void)
{
  const xx[]="test";
}
Про то, что xx[] на стеке будет, можно даже не говорить. Если нет - стековый параметр суется в секцию данных - это просто ужас, такие компиляторы если и есть в природе, они абсолютно не жизнеспособны.

А вот "test" может быть как в стеке (прямо здесь же, зачем ее иметь в других местах?), а может быть и в секции данных (если "test" много и компилятор решил заняться оптимизацией).

Crew
Попробуй сделать так

void addx(идентификация листа, напр., указатель на него)
{
 char x[8] = "йцукен";
 x[0]='q'; //чтоб не оптимизировалось
 твой Add(x)
}
[/code]

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

-------
Васкецов Сергей
http://registry.oszone.net


Отправлено: 09:02, 10-04-2003 | #20



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Строки в С\С++

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Интерфейс - Трей в 2 строки .ExeRun Microsoft Windows 7 2 31-12-2010 01:22
.NET - перечисляемые строки Surround Программирование и базы данных 3 05-10-2009 19:57
MySQL - Автозамена строки из другой строки - trigger? procedure ? BugZZ Программирование и базы данных 0 18-09-2009 09:51
строки в С++ rodman Программирование и базы данных 7 02-07-2004 12:54




 
Переход