imho.ws |
![]() |
![]() |
![]() |
# 1 |
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Перераспределение памяти - realloc
Здравствуйте, Уважаемые.
Честно говоря, даже немного стыдно с таким вопросом выходить, но уже сколько бьюсь, никак не могу решить - не понимаю. Задача элементарнейшая - надо перераспределиить память и увеличить массив еще на один элемент. Лучше сразу покажу код: Код:
#include <iostream> #include <stdlib.h> void test_func(int * argc, char ** argv){ *argv = (char*)realloc( *argv, sizeof(char*) * (++(*argc)) ); } int main(int argc, char **argv){ test_func(&argc, argv); } НО, у меня все падает с сигналом SIGABRT. Пожалуйста, объясните что я делаю не так и как надо? Да, на всякий случай, компилятор - gcc-4.4.1 Вроде как все правильно
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
![]() |
![]() |
# 2 |
Junior Member
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Во-первых, если тебя интересует почему падает с SIGABRT - потому что ты пытаешься перевыделить память по указателю argv, который любезно сформирован для тебя библиотекой CRT и является указателем на массив строк аргументов командной строки, а argc - их числом, и использовать realloc по указателю *argv (вообще каким-то образом изменять эти переменные) неверно.
Теперь - твой realloc по *argv будет перевыделять память по указателю на первую строку из этого массива - т.е., если мы запускаем программу без аргументов, то это будет указатель на строку с именем файла - а чтобы добавить элемент в подобный массив строк тебе надо использовать функцию примерно так: Код:
argv = (char**)realloc( argv, sizeof(char*) * (++(*argc)) );
__________________
"Раздвоение личности - это не болезнь, а хорошая компания." "Даже если тебя съели, по крайней мере, у тебя есть два выхода." |
![]() |
![]() |
# 3 | |
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
нет,
Цитата:
На реалкодинге высказали мысль, что его менять вообще нельзя - http://forums.realcoding.net/index.php?showtopic=23479
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
|
![]() |
![]() |
# 4 |
Junior Member
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Вот ведь.. Я эту конструкцию написал для примера - просто как добавлять элемент в подобный массив строк. Если прочтешь выше внимательней - то найдешь ту же самую мысль, что и высказали тебе на стороннем ресурсе!
Эти переменные нельзя изменять! Прочитай в интернете что-нибудь про библиотеку CRT и вызов функции main() - узнаешь как оно все устроено ![]()
__________________
"Раздвоение личности - это не болезнь, а хорошая компания." "Даже если тебя съели, по крайней мере, у тебя есть два выхода." |
![]() |
![]() |
# 5 |
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
L0rd, как добавить в подобный массив, я и так знаю, и привел выше пример. Меня интересует конкретная проблема, поставленная в первом посте. Что вообще нужно искать ответ в CRT и стандартах C/C++ я знаю и без Вас. Поэтому, если есть конкретные предложения, решения, мысли, ссылки (на те же стандарты, где описано по этому поводу) - велкам. А просто писать непроверенные неработающие примеры лучше не стоит. Уж извините за резкость.
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
![]() |
![]() |
# 6 |
Junior Member
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Например здесь можно прочитать про функцию main http://en.wikipedia.org/wiki/Main_fu...programming%29
__________________
"Раздвоение личности - это не болезнь, а хорошая компания." "Даже если тебя съели, по крайней мере, у тебя есть два выхода." |
![]() |
![]() |
# 7 |
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
L0rd, и что? Там же ни слова нету где и как выделяется память под массив argv... Или про то что его нельзя менять... Или я плохо читал?
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
![]() |
![]() |
# 8 |
СуперМод
IMHO Консультант 2005-2009 Регистрация: 14.08.2002
Адрес: Московская ПЛ, ракетный отс
Пол: Male
Сообщения: 14 496
![]() |
Вообще-то она выделяется ОС до запуска собственно программы, что вполне логично. И принадлежит эта память, соответственно, системе, а не твоей программе.
Соответственно, SIGABRT - совершенно нормальное явление. Винда в таком случае говорит "Программа выполнила недопустимую операцию и будет закрыта". И это правильно - насколь мне известно, любая ОС может позволить приложению читать "чужую" память и даже писать туда, но не перераспределять её. Т.е. если так необходимо перераспределить память под argv - необходимо не "решать" задачу в лоб, а ковырять API процесса-владельца на предмет заставить выполнять соответствующую задачу его. Это насколько я помню основы системного программирования...
__________________
Не засоряйте форум "спасибами"! Для выражения благодарности существуют ПС и репутация! Соблюдайте Правила! Распространенье наше по планете Особенно заметно вдалеке: В общественном парижском туалете Есть надписи на русском языке В. Высоцкий |
![]() |
![]() |
# 9 | |
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Борланд, не уверен что память под argv выделяется до запуска программы... Не в CRT это разве должно делаться?
Цитата:
Да нету процесса владельца-то (не, ну то-есть есть конечно, но стандартный шелл юзера скажем, не программный вроде exec). Хорошо, другой вопрос, как вариант решения - я копирую этот массив (не перераспределяю текущий), манипулирую с копией, а потом, просто изменяю указатель argv чтобы он указывал в новое место. Это-то изменение указателя будет легитимно?
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. Последний раз редактировалось Hubbitus; 04.09.2009 в 13:34. |
|
![]() |
![]() |
# 10 | |
Junior Member
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Цитата:
В любом случае, функцию realloc можно вызывать только, если по заданному указателю уже была выделена память с помощью malloc/realloc - и никак иначе. А доступ на запись в переменные argc м argv просто-напросто может быть блокирован самой библиотекой CRT - хотя бы для того, чтобы пользователь не мог ничего испортить внутри самой библиотеки CRT. Опять же, смотря в каком контексте - если внутри программы есть код, который обрабатывает командную строчку (читая из argc и argv) - то подмена указателей проходит. Даже если, что-то опять пойдет не так - например, при завершении программы - можно просто сохранить старое значение указателя и восстановить перед выходом.
__________________
"Раздвоение личности - это не болезнь, а хорошая компания." "Даже если тебя съели, по крайней мере, у тебя есть два выхода." |
|
![]() |
![]() |
# 11 | ||
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Цитата:
Цитата:
Не очень понял что пойдет не так? Тут конечно может быть утечка памяти (ну я же не могу высвободить память истинного argv как выяснилось), но Вы правы, именно к концу программы, и это получается уже совершенно не критично - по завершению вся память полюбому вернется системе. Или нет? Для чего еще я должен был бы восстанавливать этот указатель в прежнее значение?
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
||
![]() |
![]() |
# 12 |
мод
IMHO Кодер-200(6,7,8) Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Хм, ну в общем поковырялся немного с дебаггером.
Нету никакого mainCRTStartup()! Упоминания его есть только в mingw компиляторе, то есть в кросс-компилере под винду. Теперь что касается реального положения вещей, раз уж все оказалось не так, как описал L0rd, выше, если вдруг кому интересно (я пишу частный случай про изначально указанный GCC-4.4.1, glibc-2.10.1-4.i586, Linux Kernel - 2.6.31 на своей системе, не будучи специалистом в этой теме совершенно не претендую на истину этого на любой другой ОС или компонентах): Соответственно main вызывается из функции __libc_start_main. Аргументы argc и argv инициализируются вот как-то так: https://www.codeblog.org/viewsrc/gli...bp-start.h#l28 проходя через "магические" вызовы __preinit_array_start(), __preinit_array_end(), __init_array_start(), __init_array_end(), __fini_array_start(), __fini_array_end(), которые в свою очередь формируются линкером, согласно комментам. Вызываются они из __libc_csu_init, ссылка на который передается __libc_start_main как параметр init. Возвращаясь к начальной проблеме, получается что argv выделяется при помощи alloca, а не стандартных malloc, calloc и видимо, действительно не может быть ими перераспределен.
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям! Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru Pahan-Hubbitus. |
![]() |