2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Создание динамического массива внутри функции
Сообщение14.05.2017, 15:19 


07/10/15

2400
Вопрос такой.
Есть функция, в теле которой создаётся динамический массив (выделяется память и выполняется заполнение определёнными значениями), вот прототип:
Код:
int inTabl(double* Tabl, double* x, double* y, int nObs, int Ord, double q)

Tabl - это указатель на массив, а остальное - входные параметры.

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

Сейчас попробовал переделать функцию таким образом:
Код:
double* inTabl(double* x, double* y, int nObs, int Ord, double q)
,
т.е. теперь указатель на массив явно определён как возвращаемое значение.

Как ни странно, в таком виде всё работает отлично.
Подскажите пожалуйста в чём тут может быть дело? (память выделяю через malloc(), освобождаю уже в основной программе)

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 15:24 
Заслуженный участник


09/05/12
25179
Andrey_Kireew в сообщении #1216344 писал(а):
возвращает длину массива и указатель
Что значит "возвращает указатель"? По идее, он должен быть передан в функцию как параметр, функция может его использовать, но не может его "возвращать". По-видимому, где-то в этом месте Вы сделали что-то неправильное (а чтобы понять, что именно, нужно увидеть код).

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 15:49 


07/10/15

2400
Я просто неправильно выразился, конечно он передаётся в неё как параметр,
сначала я его объявляю
Код:
double* Tabl;

а затем вызываю функцию
Код:
int inTabl(Tabl, x, y, nObs, Ord, q)

она выделяет для Tabl память и потом заполняет её значениями,

но потом в основной программе по этому указателю не могу ничего прочитать.

Во втором же варианте (а там как раз функция именно возвращает указатель, т.к. он ей ни откуда из вне не передаётся), всё работает нормально.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:00 
Заслуженный участник


09/05/12
25179
Andrey_Kireew в сообщении #1216349 писал(а):
она выделяет для Tabl память и потом заполняет её значениями,
Ну и как именно выделяется память? По-видимому, Вы делаете это с помощью *alloc или new, а затем пишете в Tabl указатель на выделенную область памяти. Но, поскольку код Вы упорно приводить не хотите, и даже язык, который обсуждается, по имеющимся отрывкам однозначно не определить...

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:03 
Заслуженный участник


11/05/08
32166
Andrey_Kireew в сообщении #1216349 писал(а):
она выделяет для Tabl память и потом заполняет её значениями,

Он же передаётся по значению, а не по имени. Мало ли что там внутри функции со значением этого указателя делается -- назад-то новое значение не возвращается.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:05 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Надо понимать, что double* Tabl - это не массив, а всего лишь указатель, причём в данном случае параметр, передаваемый в функцию по значению. Обратно он никак не сможет вернуться. Если ему что-то присвоить, то это произойдёт только внутри функции.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:11 


07/10/15

2400
Вот код нерабочего варианта
Код:
# include ......
int inTabl(double* Tabl, double* x, double* y, int nObs, int Ord, double q)
{
// здесь объявления разных переменных
int Len=(Ord+nObs)<<1; Len++;
   
Tabl = (double*) malloc(SizeTabl);
memset(Tabl,0,SizeTabl);                     // заполнение нулями

    for (int ii=0; ii<nObs; ii++)
    {
     .............................
    *(Tabl+ib)=sg_y;                         
    *(Tabl+ib+nObs)=-sg_y;                 

    .............................
    }

return Len;
}

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:16 
Заслуженный участник


20/08/14
11867
Россия, Москва
Хм, а почему на это компилятор не ругается? На переопределение переменной?

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:17 
Заслуженный участник
Аватара пользователя


06/10/08
6422
Andrey_Kireew
Прочитайте уже наконец Кернигана-Ритчи, вопросы же элементарные.

Если у Вас функция выглядит примерно так
Код:
int f(double * data, int n)
{
  data = malloc(sizeof(double) * n);
  return 0;
}
и идет вызов
Код:
void main()
{
  double * a = NULL;
  f(a, 3);
}

то естественно, переменная a останется нулем, а выделенная память потеряется.

При вызове функции все параметры копируются в регистры/стек и работа внутри функции идет с этими копиями.
В данном случае значение a (NULL) при вызове f копируется в локальную переменную data, потом эта data меняется, в итоге в data остается адрес выделенной памяти, а a так и остается нулем. При выходе из функции f переменная data теряется.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:18 
Заслуженный участник


09/05/12
25179
Andrey_Kireew в сообщении #1216359 писал(а):
double* Tabl = (double*) malloc(SizeTabl);
Ну да, так и есть. Вы передаете указатель в функцию и изменяете его внутри функции. Соответственно, с внешней точки зрения ничего не происходит, информация о том, что указатель изменился, обратно не возвращается.

-- 14.05.2017, 16:19 --

Dmitriy40 в сообщении #1216361 писал(а):
Хм, а почему на это компилятор не ругается? На переопределение переменной?
По стандарту это не ошибка. Мог бы выскочить warning, но это зависит от настроек компилятора.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:24 
Заслуженный участник


20/08/14
11867
Россия, Москва
Pphantom в сообщении #1216363 писал(а):
По стандарту это не ошибка. Мог бы выскочить warning, но это зависит от настроек компилятора.
Ужасно. Оно должно было выскочить. И если кто-то его запрещает/отменяет, то без глубокого понимания происходящего он делает это очень зря. ИМХО. Я при отладке программ включаю все варнинги и с причиной каждого внимательно разбираюсь.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение14.05.2017, 16:26 


07/10/15

2400
Уже немножко начинаю догадываться

-- 14.05.2017, 17:35 --

Всё как пишет Xaositect , код был с ошибкой - сейчас исправлено.

-- 14.05.2017, 17:54 --

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

Код:
int inTabl(double** Tabl, double* x, double* y, int nObs, int Ord, double q)
{
*Tabl = (double*) malloc(SizeTabl);
memset(*Tabl,0,SizeTabl);
..............
return Len;
}



void main()
{
double** Tabl;
int Len=inTabl(* Tabl, x, y, nObs, Ord, q);

}


в таком виде будет правильно?

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение15.05.2017, 17:54 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Ещё освойте замечательный форумный тег syntax.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение15.05.2017, 18:41 
Заслуженный участник


09/05/12
25179
Andrey_Kireew в сообщении #1216367 писал(а):
Напрашивается вывод, что нужно использовать указатель на указатель
Именно.

 Профиль  
                  
 
 Re: Создание динамического массива внутри функции
Сообщение15.05.2017, 19:09 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Andrey_Kireew в сообщении #1216367 писал(а):
Напрашивается вывод, что нужно использовать указатель на указатель

Зависит от языка.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group