imho.ws
IMHO.WS  

Вернуться   IMHO.WS > Компьютеры > Программирование
Опции темы
Старый 31.08.2009, 12:22     # 1
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
Перераспределение памяти - 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.
Hubbitus вне форума  
Старый 01.09.2009, 23:53     # 2
L0rd
Junior Member
 
Аватар для L0rd
 
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180

L0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd Сэнсэй
Во-первых, если тебя интересует почему падает с SIGABRT - потому что ты пытаешься перевыделить память по указателю argv, который любезно сформирован для тебя библиотекой CRT и является указателем на массив строк аргументов командной строки, а argc - их числом, и использовать realloc по указателю *argv (вообще каким-то образом изменять эти переменные) неверно.

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

Код:
argv = (char**)realloc( argv, sizeof(char*) * (++(*argc)) );
__________________
"Раздвоение личности - это не болезнь, а хорошая компания."
"Даже если тебя съели, по крайней мере, у тебя есть два выхода."

L0rd вне форума  
Старый 02.09.2009, 12:40     # 3
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
нет,
Цитата:
Сообщение от L0rd Посмотреть сообщение
а чтобы добавить элемент в подобный массив строк тебе надо использовать функцию примерно так:
Результат тот же - SIGABRT.

На реалкодинге высказали мысль, что его менять вообще нельзя - http://forums.realcoding.net/index.php?showtopic=23479
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям!

Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru
Pahan-Hubbitus.
Hubbitus вне форума  
Старый 03.09.2009, 01:19     # 4
L0rd
Junior Member
 
Аватар для L0rd
 
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180

L0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd Сэнсэй
Цитата:
Сообщение от Hubbitus Посмотреть сообщение
Результат тот же - SIGABRT.
Вот ведь.. Я эту конструкцию написал для примера - просто как добавлять элемент в подобный массив строк. Если прочтешь выше внимательней - то найдешь ту же самую мысль, что и высказали тебе на стороннем ресурсе!
Эти переменные нельзя изменять!
Прочитай в интернете что-нибудь про библиотеку CRT и вызов функции main() - узнаешь как оно все устроено
__________________
"Раздвоение личности - это не болезнь, а хорошая компания."
"Даже если тебя съели, по крайней мере, у тебя есть два выхода."

L0rd вне форума  
Старый 03.09.2009, 10:44     # 5
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
L0rd, как добавить в подобный массив, я и так знаю, и привел выше пример. Меня интересует конкретная проблема, поставленная в первом посте. Что вообще нужно искать ответ в CRT и стандартах C/C++ я знаю и без Вас. Поэтому, если есть конкретные предложения, решения, мысли, ссылки (на те же стандарты, где описано по этому поводу) - велкам. А просто писать непроверенные неработающие примеры лучше не стоит. Уж извините за резкость.
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям!

Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru
Pahan-Hubbitus.
Hubbitus вне форума  
Старый 03.09.2009, 19:49     # 6
L0rd
Junior Member
 
Аватар для L0rd
 
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180

L0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd Сэнсэй
Например здесь можно прочитать про функцию main http://en.wikipedia.org/wiki/Main_fu...programming%29
__________________
"Раздвоение личности - это не болезнь, а хорошая компания."
"Даже если тебя съели, по крайней мере, у тебя есть два выхода."

L0rd вне форума  
Старый 04.09.2009, 11:33     # 7
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
L0rd, и что? Там же ни слова нету где и как выделяется память под массив argv... Или про то что его нельзя менять... Или я плохо читал?
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям!

Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru
Pahan-Hubbitus.
Hubbitus вне форума  
Старый 04.09.2009, 11:49     # 8
Borland
СуперМод
IMHO Консультант 2005-2009
 
Аватар для Borland
 
Регистрация: 14.08.2002
Адрес: Московская ПЛ, ракетный отс
Пол: Male
Сообщения: 14 496

Borland - Гад и сволочь
Цитата:
Сообщение от Hubbitus Посмотреть сообщение
где и как выделяется память под массив argv...
Вообще-то она выделяется ОС до запуска собственно программы, что вполне логично. И принадлежит эта память, соответственно, системе, а не твоей программе.
Соответственно, SIGABRT - совершенно нормальное явление. Винда в таком случае говорит "Программа выполнила недопустимую операцию и будет закрыта". И это правильно - насколь мне известно, любая ОС может позволить приложению читать "чужую" память и даже писать туда, но не перераспределять её.
Т.е. если так необходимо перераспределить память под argv - необходимо не "решать" задачу в лоб, а ковырять API процесса-владельца на предмет заставить выполнять соответствующую задачу его.
Это насколько я помню основы системного программирования...
__________________
Не засоряйте форум "спасибами"! Для выражения благодарности существуют ПС и репутация! Соблюдайте Правила!
Распространенье наше по планете
Особенно заметно вдалеке:
В общественном парижском туалете
Есть надписи на русском языке

В. Высоцкий

Borland вне форума  
Старый 04.09.2009, 13:31     # 9
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
Борланд, не уверен что память под argv выделяется до запуска программы... Не в CRT это разве должно делаться?

Цитата:
Сообщение от Borland Посмотреть сообщение
И это правильно - насколь мне известно, любая ОС может позволить приложению читать "чужую" память и даже писать туда,
нет. Для непривелигированных приложений это не возможно, будет ошибка segmentation failed, в виндах что-то вроде ошибки "Память по адресу 0xFFFFFF" не может быть read (меня всегда веселило такое сообщение).

Цитата:
Сообщение от Borland Посмотреть сообщение
Т.е. если так необходимо перераспределить память под argv - необходимо не "решать" задачу в лоб, а ковырять API процесса-владельца на предмет заставить выполнять соответствующую задачу его.
Да нету процесса владельца-то (не, ну то-есть есть конечно, но стандартный шелл юзера скажем, не программный вроде exec). Хорошо, другой вопрос, как вариант решения - я копирую этот массив (не перераспределяю текущий), манипулирую с копией, а потом, просто изменяю указатель argv чтобы он указывал в новое место. Это-то изменение указателя будет легитимно?
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям!

Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru
Pahan-Hubbitus.

Последний раз редактировалось Hubbitus; 04.09.2009 в 13:34.
Hubbitus вне форума  
Старый 04.09.2009, 20:03     # 10
L0rd
Junior Member
 
Аватар для L0rd
 
Регистрация: 02.08.2005
Адрес: Пенза
Пол: Male
Сообщения: 180

L0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd СэнсэйL0rd Сэнсэй
Цитата:
Сообщение от Hubbitus Посмотреть сообщение
Борланд, не уверен что память под argv выделяется до запуска программы... Не в CRT это разве должно делаться?
Вот как все происходит. Точка входа в любое приложение - библиотечная функция mainCRTStartup() - она считывает указатель на командную строку запускаемого приложения, выполняет всю необходимую инициализацию, формирует переменные argc и argv, а затем вызывает нашу функцию main(). Откуда взялась эта память - была ли она выделена в функции создании процесса или выделена из "кучи" процесса - мы не знаем и знать не должны.
В любом случае, функцию realloc можно вызывать только, если по заданному указателю уже была выделена память с помощью malloc/realloc - и никак иначе. А доступ на запись в переменные argc м argv просто-напросто может быть блокирован самой библиотекой CRT - хотя бы для того, чтобы пользователь не мог ничего испортить внутри самой библиотеки CRT.


Цитата:
Сообщение от Hubbitus Посмотреть сообщение
я копирую этот массив (не перераспределяю текущий), манипулирую с копией, а потом, просто изменяю указатель argv чтобы он указывал в новое место. Это-то изменение указателя будет легитимно?
Опять же, смотря в каком контексте - если внутри программы есть код, который обрабатывает командную строчку (читая из argc и argv) - то подмена указателей проходит. Даже если, что-то опять пойдет не так - например, при завершении программы - можно просто сохранить старое значение указателя и восстановить перед выходом.
__________________
"Раздвоение личности - это не болезнь, а хорошая компания."
"Даже если тебя съели, по крайней мере, у тебя есть два выхода."

L0rd вне форума  
Старый 05.09.2009, 11:13     # 11
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
Цитата:
Сообщение от L0rd Посмотреть сообщение
Вот как все происходит. Точка входа в любое приложение - библиотечная функция mainCRTStartup() - она считывает указатель на командную строку запускаемого приложения, выполняет всю необходимую инициализацию, формирует переменные argc и argv, а затем вызывает нашу функцию main().
Ну вот это уже ближе к телу, приблизительно так я себе и представлял... Теперь, подскажите еще какой библиотеки эта самая функция mainCRTStartup()? Было бы логично предположить что glibc, но я грепнул его сурсы - нету. Посмотрел также в ядре... Где искать-то ее исходник?


Цитата:
Сообщение от L0rd Посмотреть сообщение
Опять же, смотря в каком контексте - если внутри программы есть код, который обрабатывает командную строчку (читая из argc и argv) - то подмена указателей проходит.
Собственно для этого я и собираюсь его подменить, т.к. идет сопряжение с Сишным АПИ, и мне именно в argv надо запихать свой аргумент. И я больше спрашивал не подходит ли, это я предположил что подойдет сам, я спрашиваю, можно ли, менять этот указатель? Нет ли у него опять какого-то статуса особого? Я думал что и просто перераспределить память его можно...

Цитата:
Сообщение от L0rd Посмотреть сообщение
Даже если, что-то опять пойдет не так - например, при завершении программы - можно просто сохранить старое значение указателя и восстановить перед выходом.
Не очень понял что пойдет не так? Тут конечно может быть утечка памяти (ну я же не могу высвободить память истинного argv как выяснилось), но Вы правы, именно к концу программы, и это получается уже совершенно не критично - по завершению вся память полюбому вернется системе. Или нет? Для чего еще я должен был бы восстанавливать этот указатель в прежнее значение?
__________________
Я делаю Линукс! Присоединяйтесь к свободным людям!

Связаться со мной всегда можно по джабберу: Hubbitus@jabber.ru
Pahan-Hubbitus.
Hubbitus вне форума  
Старый 05.09.2009, 13:33     # 12
Hubbitus
мод
IMHO Кодер-200(6,7,8)
 
Регистрация: 29.03.2003
Адрес: Saint-Petersburg, Russia
Пол: Male
Сообщения: 2 734

Hubbitus Бог с наворотамиHubbitus Бог с наворотами
Hubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотамиHubbitus Бог с наворотами
Хм, ну в общем поковырялся немного с дебаггером.
Нету никакого 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.
Hubbitus вне форума  

Теги (метки)
c/c++, memory, realloc


Ваши права в разделе
Вы НЕ можете создавать новые темы
Вы не можете отвечать в темах.
Вы НЕ можете прикреплять вложения
Вы НЕ можете редактировать свои сообщения

BB код Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 02:54.




Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.