2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 Си передача указателя между функциями
Сообщение28.10.2021, 11:33 
Заблокирован


19/02/13

2388
Нет ли в приведённой ниже схеме работы с памятью какой-либо ошибки? На локальной машине всё работает, на codewars вылетает с ошибкой "SIGSEGV (11). Invalid memory access." - без подробностей.
код: [ скачать ] [ спрятать ]
Используется синтаксис C
const char* r;//глобальная переменная

const char** get_pins(const char* observed, size_t* count) {
//кусок кода
    char *res = malloc(*count*(l)*sizeof(size_t));//создаю массив
    r = res;//сохраняю указатель на массив в глобальную переменную, чтобы вызывающая программа могла работать с ним после завершения работы функции
//кусок кода
    return &r;//возвращаю указатель на массив через глобальную переменную
}

//Эта функция освобождает память, занятую массивом
void free_pins(const char ** pins) {
    free(pins);
}

int main(){
//кусок кода
    const char *p;
    p = *get_pins(pin, &hmn);//вызываю функцию, получаю указатель на массив в глобальной переменной
//кусок кода

    free_pins(&p);//вызвыаю функцию, освобождающую память, передаю ей указатель на глобальную переменную
}

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


16/07/14
8464
Цюрих
Ошибки есть. Например у вас зовется free с адресом переменной на стеке.
И вообще код ужасный, мешанина из указателей на указатели и глобальных переменных на пустом месте. Зачем возвращать указатель на глобальную переменную? Зачем тут вообще глобальная переменная?

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:07 
Заблокирован


19/02/13

2388
mihaild в сообщении #1536651 писал(а):
мешанина из указателей на указатели


Таковы условия задачи.
код: [ скачать ] [ спрятать ]
Используется синтаксис C
#include <stdlib.h>

//Function should return an array of c-strings with all possible PINs.
//It must allocate all required meomry, but there are no requirements
//as to how it should be done. It must be possible to free
//allocated memory with a call to free_pins.
//Upon return, count should contain the amount of returned PINs.
const char** get_pins(const char* observed, size_t* count) {
    *count = 1;
    return NULL;
}

//This function will be called once per every call to get_pins
//with a pointer value returned by such call.
void free_pins(const char ** pins) {
    //...do your cleanup, if necessary
}


mihaild в сообщении #1536651 писал(а):
Зачем тут вообще глобальная переменная?


А как иначе обеспечить возможность для вызывающей функции работать с массивом, созданным вызываемой функцией, после завершения её работы? Если я передаю в main() &res, который существует только внутри функции, то вылетает ошибка - ведь по завершению работы функции созданная в ней res пропадает.

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


16/07/14
8464
Цюрих
Vladimir-80 в сообщении #1536653 писал(а):
Таковы условия задачи.
Тут требуется совершенно не то, что у вас сделано. Требуют массив строк, так чтобы можно было брать у возвращаемого массива нулевой элемент, первый и т.д.
Всё равно непонятно зачем count передавать по указателю, но это уже мелочи.
Vladimir-80 в сообщении #1536653 писал(а):
Если я передаю в main() &res, который существует только внутри функции, то вылетает ошибка - ведь по завершению работы функции созданная в ней res пропадает
Так вы не передавайте указатель на локальную переменную. Вы честно создайте переменную типа char**, инициализируйте её как нужно, и возвращайте по значению.

Перечитайте, что вообще такое указатели, строки и т.д.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:30 
Заблокирован


19/02/13

2388
mihaild в сообщении #1536655 писал(а):
Требуют массив строк, так чтобы можно было брать у возвращаемого массива нулевой элемент, первый и т.д.


Именно это у меня и сделано. Размер массива заранее неизвестен, он рассчитывается на основании переданных параметров. Соответственно, быть ему в куче. Я так его и создаю, и возвращаю указатель на его начало с помощью глобальной переменной, которая не пропадёт после завершения работы функции.

mihaild в сообщении #1536655 писал(а):
зачем count передавать по указателю


Count создаётся вызывающей функцией, существует в ней, моя функция только меняет её значение по указателю. Так поставлены условия, так я и свою тестовую main() сделал, в которой всё работает.
mihaild в сообщении #1536655 писал(а):
Так вы не передавайте указатель на локальную переменную. Вы честно создайте переменную типа char**, инициализируйте её как нужно, и возвращайте по значению.


Попробую.
А в варианте с глобальной переменной что не так-то? Ведь на локальной машине всё работает без ошибок. Где подвох?

-- 28.10.2021, 12:32 --

mihaild в сообщении #1536655 писал(а):
переменную типа char**, инициализируйте её как нужно, и возвращайте по значению


Похоже, именно на такое решение заточена задача и тесты. Сейчас проверю.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:43 


18/09/21
1683
Тут ошибка:
Используется синтаксис C++
free(pins);

Нужно
Используется синтаксис C++
free(*pins);

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


16/07/14
8464
Цюрих
Vladimir-80 в сообщении #1536659 писал(а):
Именно это у меня и сделано.
Нет, у вас создается одна строка (char*). А нам явно нужен массив строк.
Vladimir-80 в сообщении #1536659 писал(а):
Count создаётся вызывающей функцией, существует в ней, моя функция только меняет её значение по указателю
А, ну если count надо менять, то всё правильно.
Vladimir-80 в сообщении #1536659 писал(а):
А в варианте с глобальной переменной что не так-то?
Как минимум
mihaild в сообщении #1536651 писал(а):
у вас зовется free с адресом переменной на стеке

Vladimir-80 в сообщении #1536659 писал(а):
Ведь на локальной машине всё работает без ошибок
Если я правильно помню, codewars не дает обвязку для тестов. А вы, судя по фрагментам кода и описанию, сделали вообще не то, что просили.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:47 


18/09/21
1683
Вообще лучше так
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
const char* get_pins(const char* observed, size_t count) {
//кусок кода
    const char *res = malloc(count*(l)*sizeof(count));//создаю массив
    return res;
}

//Эта функция освобождает память, занятую массивом
void free_pins(const char *pins) {
    free(pins);
}

int main(){
//кусок кода
    const char *p;
    p = get_pins(pin, hmn);
//кусок кода
    free_pins(p);
}

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:57 
Заблокирован


19/02/13

2388
mihaild в сообщении #1536663 писал(а):
Нет, у вас создается одна строка (char*). А нам явно нужен массив строк.


А разве malloc может создать массив строк? Она просто забирает кусок памяти нужного размера, а на строки и столбцы я уже делю эту память сам, обращаясь к конкретному элементу с помощью несложных вычислений типа $*(p+i*m+j)$, где $p$ - указатель на массив, $m$ - количество столбцов, $i$ - индекс строки, $j$ - индекс столбца.
В Си массив строк вообще весьма условное понятие - это по факту всегда одна длинная строка в памяти, и задача программиста правильно ей распорядиться.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:00 


18/09/21
1683
Можно по разному делать.
Можно выделить память на массив указателей, а потом для каждого элемента массива выделить память под одну строку.
А можно сразу один буфер под все строки выделить.

-- 28.10.2021, 13:02 --

Vladimir-80 в сообщении #1536667 писал(а):
В Си массив строк вообще весьма условное понятие - это по факту всегда одна длинная строка в памяти
Нет, это массив указателей.
Одна строка - это указатель на кусок памяти. А массив строк - это указаетль на кусок памяти в которой лежат указатели на строки.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:05 
Заблокирован


19/02/13

2388
zykov в сообщении #1536664 писал(а):
Вообще лучше так


Если вовзращать res, программа завершается с ошибкой, вызывающая функция не может обработать результат.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:09 


18/09/21
1683
Важен 'const'
Используется синтаксис C++
const char *res

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:09 
Заблокирован


19/02/13

2388
zykov в сообщении #1536668 писал(а):
Можно выделить память на массив указателей, а потом для каждого элемента массива выделить память под одну строку.


Наверно можно и так. Но в данном случае, на мой взгляд, проще и эффективней выделить память сразу под весь результат. Задача - составить список возможных вариантов полученного параметра. То есть получил $n$ цифр - возвращаю $x$ вариантов строго по $n$ цифр, а $x$ зависит от входящего набора.

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:14 


18/09/21
1683
Насчёт 'const', то не понятно зачем он там кстати, если вы туда будете строки записывать...

 Профиль  
                  
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:15 
Заблокирован


19/02/13

2388
zykov в сообщении #1536673 писал(а):
Важен 'const'

Если объявляю
Используется синтаксис C
const char *res = malloc(*count*(l)*sizeof(size_t));

то на
Используется синтаксис C
*(res+j*l+i) = vrs[p][m];

получаю ошибку "|44|error: assignment of read-only location '*(res + ((sizetype)(j * l) + (sizetype)i))'|"

-- 28.10.2021, 13:16 --

zykov в сообщении #1536676 писал(а):
Насчёт 'const', то не понятно зачем он там кстати, если вы туда будете строки записывать...


Вопрос хороший, но так поставлена задача. Мне тоже это в глаза бросилось.

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

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



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

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


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

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