С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/14: Рейтинг темы: голосов - 14, средняя оценка - 4.57
4 / 4 / 0
Регистрация: 23.03.2010
Сообщений: 16

Std::string портит память

24.03.2010, 00:52. Показов 2766. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Столкнулся с интересной проблемой. Лет 6 назад использовал одну прогу под ASPLinux 7.2. Исходники компилировались нормально и прога работала (gcc был, по-моему, версии 2.95).
Сейчас появился интерес реанимировать этот проект, но уже под Russian Fedora 12. Компиляция и установка прошли нормально, но при запуске программа выдала «Segmentation fault».
Исследование проблемы показало, что сбой происходит на , казалось бы, абсолютно нормальном участке кода:

C++
1
2
    CFilter* f = new CFilter;
    Filters.push_back(f); // <-------- здесь!
Причем CFilter — некий класс, потомок класса CFilterBase, а Filters является вектором:
C++
1
class CFilters : public vector<CFilterBase*>
. Вроде все нормально.

Поиски корней проблемы привели к следующему. Оказывается, содержимое Filters портится при выполнении следующей команды:

C++
1
string libfile = dblib_paths[i] + "lib" + DBType + "db.so";
где dblib_paths — vector (количество элементов — 1, i=0), DBType — string, т.е.
C++
1
2
        std::string DBType;
        vector<string> dblib_paths;
Причем происходит следующее. dblib_paths и Filters располагаются в памяти друг за другом.
При выполнении этой строчки происходит пристыковка "/lib" + DBType + "db.so" к dblib_paths непосредственно в месте ее расположения и потом присвоение адреса этой области памяти переменной libfile. Причем пристыковка залезает на область памяти, занимаемой Filters, что впоследствии и приводит к сбою программы.

После выполнения этой строчки libfile располагается там же, где был dblib_paths[0]. Хотя, по логике, при присвоении переменной класса string должно происходить копирование объекта. Т.е. менеджер памяти должен отслеживать ситуацию.

Моделирование данной ситуации на простой программе показало, что действительно, менеджер памяти отслеживает эту ситуацию и при выполнении такой же строчки происходит копирование содержимого [I]dblib_paths в свободную область памяти и там уже происходит пристыковка всего остального. И libfile имеет уже другой адрес, чем [I]dblib_paths.

Вопрос: почему так происходит? Почему раньше (на ASPLinux 7.2) эта прога работала, а теперь, в более новой версии Linux'а — такие косяки? Что-то с реализацией класса string? Или ключи какие надо установить?

P.S. Предвидя вопросы типа где makefile, версия gcc и т.п. скажу, что прога эта - поисковая машина aspseek (www.aspseek.org), там все исходники.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.03.2010, 00:52
Ответы с готовыми решениями:

ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri
на вод поступают 2 строки типа string. определить количество вхождений строки 2 в строку 1 ошибка...

Std::vector<std::pair<std::vector<int>::iterator, std::vector<int>::iterator>
Вопрос по вектору. Допустим есть вектор, std::vector&lt;int&gt; vec; на каком - то этапе заполнения я...

На основе исходного std::vector<std::string> содержащего числа, создать std::vector<int> с этими же числами
подскажите есть вот такая задача. Есть список . Создать второй список, в котором будут все эти же...

8
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
24.03.2010, 04:06
выполни:
strace -v -olog.txt ./programm_name
в логе, возможно сам поймешь в чем причина.
если нет, выкладывай лог.

еще вариант, заюзать valgrind
0
4 / 4 / 0
Регистрация: 23.03.2010
Сообщений: 16
25.03.2010, 12:26  [ТС]
Сделал strace -v -olog.txt ./index.
Ничего не прояснилось.
Не знаю, нужно ли выкладывать весь файл, но вот самые IMHO интересные места:

интересные места
execve("./index", ["./index"], ["ORBIT_SOCKETDIR=/tmp/orbit-aspseek", "HOSTNAME=zhost.localdomain", "IMSETTINGS_INTEGRATE_DESKTOP=yes", "SHELL=/bin/bash", "TERM=xterm", "HISTSIZE=1000", "XDG_SESSION_COOKIE=a9bff6c27c55ac971365 62054b916719-1269429242.1"..., "GTK_RC_FILES=/etc/gtk/gtkrc:/home/aspseek/.gtkrc-1.2-gnome2", "WINDOWID=69206019", "QTDIR=/usr/lib/qt-3.3", "QTINC=/usr/lib/qt-3.3/include", "IMSETTINGS_MODULE=none", "USER=aspseek", "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00: pi=40;33:so=01;35:do=01;3"..., "SSH_AUTH_SOCK=/tmp/keyring-XWkPyc/socket.ssh", "GNOME_KEYRING_SOCKET=/tmp/keyring-XWkPyc/socket", "USERNAME=aspseek", "SESSION_MANAGER=local/unix:@/tmp/.ICE-unix/1745,unix/unix:/tmp/."..., "MC_TMPDIR=/tmp/mc-aspseek", "PATH=/usr/lib/qt-3.3/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/u"..., "MAIL=/var/spool/mail/aspseek", "DESKTOP_SESSION=gnome", "QT_IM_MODULE=xim", "PWD=/home/aspseek/work/aspseek-1.2.15/src", "XMODIFIERS=@im=none", "GDM_KEYBOARD_LAYOUT=us", "GNOME_KEYRING_PID=1738", "KDE_IS_PRELINKED=1", "LANG=ru_RU.UTF-8", "GDM_LANG=ru_RU.UTF-8", "KDEDIRS=/usr", "GDMSESSION=gnome", "HISTCONTROL=ignorespace", "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass", "SHLVL=3", "HOME=/home/aspseek", "GNOME_DESKTOP_SESSION_ID=this-is-deprecated", "MC_SID=2189", "LOGNAME=aspseek", "CVS_RSH=ssh", "QTLIB=/usr/lib/qt-3.3/lib", "DBUS_SESSION_BUS_ADDRESS=unix:abstr act=/tmp/dbus-oLoc3xq7DO,guid"..., "LESSOPEN=|/usr/bin/lesspipe.sh %s", "DISPLAY=:0.0", "G_BROKEN_FILENAMES=1", "COLORTERM=gnome-terminal", "XAUTHORITY=/var/run/gdm/auth-for-aspseek-jVOUtJ/database", "OLDPWD=/home/aspseek/work/aspseek-1.2.15", "_=/usr/bin/strace"]) = 0
brk(0) = 0x937d000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78e2000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat64(3, {st_dev=makedev(8, 1), st_ino=176639, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=240, st_size=119297, st_atime=2010/03/23-23:31:20, st_mtime=2010/03/23-23:31:08, st_ctime=2010/03/23-23:31:08}) = 0
mmap2(NULL, 119297, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb78c4000
close(3) = 0
open("/lib/libdl.so.2", O_RDONLY) = 3
.....
.....
open("/usr/lib/libstdc++.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0 \1\0\0\0 \366I\0004\0\0\0\260\32\16\0\0\0\0\0004\ 0 \0\10\0(\0!\0 \0\1\0\0\0\0\0\0\0\0\240E\0"..., 512) = 512
fstat64(3, {st_dev=makedev(8, 1), st_ino=163990, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=1808, st_size=925656, st_atime=2010/03/23-16:11:40, st_mtime=2010/01/27-22:07:18, st_ctime=2010/03/20-15:17:41}) = 0
mmap2(0x45a000, 953260, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x45a000
mmap2(0x537000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xdc) = 0x537000
mmap2(0x53d000, 23468, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x53d000
close(3) = 0
........
........
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78c2000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78c1000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb78c16d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xbfc000, 8192, PROT_READ) = 0
mprotect(0xc4f000, 4096, PROT_READ) = 0
mprotect(0x537000, 16384, PROT_READ) = 0
mprotect(0xc21000, 4096, PROT_READ) = 0
mprotect(0xc07000, 4096, PROT_READ) = 0
mprotect(0xa89000, 4096, PROT_READ) = 0
munmap(0xb78c4000, 119297) = 0
set_tid_address(0xb78c1738) = 2369
set_robust_list(0xb78c1740, 0xc) = 0
futex(0xbf80a2d0, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0xbf80a2d0, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_RE ALTIME, 1, NULL, bf80a2e0) = -1 EAGAIN (Resource temporarily unavailable)
rt_sigaction(SIGRTMIN, {0xc0f3e0, [], SA_SIGINFO}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {0xc0f870, [], SA_RESTART|SA_SIGINFO}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=10240*1024, rlim_max=RLIM_INFINITY}) = 0
uname({sysname="Linux", nodename="zhost.localdomain", release="2.6.31.5-127.fc12.i686.PAE", version="#1 SMP Sat Nov 7 21:25:57 EST 2009", machine="i686"}) = 0
brk(0) = 0x937d000
brk(0x939e000) = 0x939e000
brk(0x93bf000) = 0x93bf000
brk(0x93e0000) = 0x93e0000
getuid32() = 501
rt_sigaction(SIGSEGV, {0x808d5be, [], SA_RESETHAND}, {SIG_DFL, [], 0}, 8) = 0
fstat64(1, {st_dev=makedev(0, 10), st_ino=4, st_mode=S_IFCHR|0620, st_nlink=1, st_uid=501, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 1), st_atime=2010/03/24-14:41:24, st_mtime=2010/03/24-14:41:24, st_ctime=2010/03/24-14:16:13}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78e1000
Здесь я вывожу свойства Filters, который потом портится
write(1, "1.Filters: empty=1 capacity=0 size=0 max_size=1073741823\n", 48) = 48
write(1, "2.Filters: empty=1 capacity=0 size=0 max_size=1073741823\n", 48) = 48
Вот здесь эта строчка :
string libfile = dblib_paths[i] + "/lib" + DBType + "db-" VERSION ".so";

write(1, "3.Filters: empty=0 capacity=-191917709 size=29360180 max_size=1073741823\n", 64) = 64
ВСЁ! Filters испортился!
write(1, " ---> /usr/local/aspseek/lib/libmysqldb-1.2.15.so\n", 50) = 50 <---- вывод содержимого libfile
write(1, "libfile: empty=0 capacity=1073741824 size=43 max_size=1073741820\n", 63) = 63
write(1, "4.Filters:empty=0 capacity=-191917709 size=29360180 max_size=107374182"..., 66) = 66
futex(0xc08068, FUTEX_WAKE_PRIVATE, 2147483647) = 0
open("/usr/local/aspseek/lib/libmysqldb-1.2.15.so", O_RDONLY) = 3

.........
А вот здесь уже происходит обращение Filters.push_baсk(f); Как видно его свойства больше не меняются
write(1, "Filters:empty=0 capacity=-191917709 size=29360180 max_size=1073741823\n", 62) = 62
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
write(2, "Address of param: bf802e70\n", 27) = 27
sigreturn() = ? (mask now [])
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV (core dumped) +++


Добавлено через 8 минут
Цитата Сообщение от taras atavin Посмотреть сообщение
Я щас делаю свою реализацию строк, назвав их типом TString. Кинуть тебе, когда отлажу?
Вообще-то я подумываю, чтобы вставить в программу свою реализацию string. Поэтому это предложение может быть полезно. Буду очень благодарен.

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

Добавлено через 21 час 8 минут
Ошибка найдена!!!
Как и ожидалось, именно в программе, а не в string
Причина - в грубом вмешательстве в работу класса string через изменение статического члена класса через дальний указатель. Видимо, это работало под ранними версиями Linux, а впоследствии, может быть, программная реализация класса слегка изменилась.

Всем спасибо за советы!!!
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.03.2010, 13:00
Цитата Сообщение от Kwal Посмотреть сообщение
Причина - в грубом вмешательстве в работу класса string через изменение статического члена класса через дальний указатель
А для истории опиши, что там делалось. Или слишком муторно?
0
4 / 4 / 0
Регистрация: 23.03.2010
Сообщений: 16
25.03.2010, 17:33  [ТС]
Вот пара строчек из текста программы, приводящая к ошибке, с комментариями автора.

C++
1
2
3
4
5
6
7
    string DBName1;
 
    // This is just to set reference counter of static member
    // of STL string class to big value
    // so it will never reach 0 in SMP system
    long* ref = (long*)DBName1.data() - 2;
    *ref = 0x40000000;
Я думаю, тут все понятно.
Только мне не совсем понятно, зачем сделано именно так. И в чем особенность работы класса string (или классов со статическими членами?) на SMP system?
Но это уже другой вопрос. Может, правда, кто-нибудь из спецов разъяснит для общего образования.
2
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.03.2010, 17:59
Автор таким кодом, конечно же, жжот не по детски. С чем могут быть проблемы на SMP - фантазии как-то не хватает, чтобы понять. Правда я исхожу из того, что SMP - это многопроцессорная система. Хз, может есть другая аббревиатура
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
25.03.2010, 18:22
бред полный!
аффтора линчевать за такое!
0
4 / 4 / 0
Регистрация: 23.03.2010
Сообщений: 16
25.03.2010, 22:35  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
бред полный!
аффтора линчевать за такое!

Не надо линчевать автора! Автор - уважаемый человек! Программа хорошая и ведь работала раньше...
Но пожурить надо, согласен
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
25.03.2010, 23:17
Цитата Сообщение от Kwal Посмотреть сообщение
Автор - уважаемый человек!
я себя !уважаемым! не считаю(в том смысле слова, который вы имели ввиду), но такого я бы никогда не написал.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.03.2010, 23:17
Помогаю со студенческими работами здесь

Std::unordered_multimap<std::string, std::unordered_multimap<int, int>>
Приветствую. Интересует вопрос, как можно обращаться к контейнеру? Хотелось бы по map, но так не...

Поиск в std::vector < std::pair<UInt32, std::string> >
Подскажите пожалуйста, как осуществить поиск элемента в std::vector &lt; std::pair&lt;UInt32,...

Не освобождается память std::string после использования std::bind
Всем привет! Есть система, которая подгружает из внешних библиотек функции, упаковывает их в...

Запрошено преобразование от ‘const std::string*’ к нескалярному типу ‘std::string’
private: std::string firstName; }; std::string ClientData::getFirstName() const{ ...

Перевод строк std::string, std::wstring в Unicode (String)
Собственно столкнулся с проблемой, как корректно перевести к примеру текст из Edit1-&gt;Text в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru