2014 dxdy logo

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

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




На страницу 1, 2, 3  След.
 
 Си передача указателя между функциями
Сообщение28.10.2021, 11:33 
Нет ли в приведённой ниже схеме работы с памятью какой-либо ошибки? На локальной машине всё работает, на 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 
Аватара пользователя
Ошибки есть. Например у вас зовется free с адресом переменной на стеке.
И вообще код ужасный, мешанина из указателей на указатели и глобальных переменных на пустом месте. Зачем возвращать указатель на глобальную переменную? Зачем тут вообще глобальная переменная?

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:07 
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 
Аватара пользователя
Vladimir-80 в сообщении #1536653 писал(а):
Таковы условия задачи.
Тут требуется совершенно не то, что у вас сделано. Требуют массив строк, так чтобы можно было брать у возвращаемого массива нулевой элемент, первый и т.д.
Всё равно непонятно зачем count передавать по указателю, но это уже мелочи.
Vladimir-80 в сообщении #1536653 писал(а):
Если я передаю в main() &res, который существует только внутри функции, то вылетает ошибка - ведь по завершению работы функции созданная в ней res пропадает
Так вы не передавайте указатель на локальную переменную. Вы честно создайте переменную типа char**, инициализируйте её как нужно, и возвращайте по значению.

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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:30 
mihaild в сообщении #1536655 писал(а):
Требуют массив строк, так чтобы можно было брать у возвращаемого массива нулевой элемент, первый и т.д.


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

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


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


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

-- 28.10.2021, 12:32 --

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


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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:43 
Тут ошибка:
Используется синтаксис C++
free(pins);

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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 12:46 
Аватара пользователя
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 
Вообще лучше так
код: [ скачать ] [ спрятать ]
Используется синтаксис 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 
mihaild в сообщении #1536663 писал(а):
Нет, у вас создается одна строка (char*). А нам явно нужен массив строк.


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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:00 
Можно по разному делать.
Можно выделить память на массив указателей, а потом для каждого элемента массива выделить память под одну строку.
А можно сразу один буфер под все строки выделить.

-- 28.10.2021, 13:02 --

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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:05 
zykov в сообщении #1536664 писал(а):
Вообще лучше так


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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:09 
Важен 'const'
Используется синтаксис C++
const char *res

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:09 
zykov в сообщении #1536668 писал(а):
Можно выделить память на массив указателей, а потом для каждого элемента массива выделить память под одну строку.


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

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:14 
Насчёт 'const', то не понятно зачем он там кстати, если вы туда будете строки записывать...

 
 
 
 Re: Си передача указателя между функциями
Сообщение28.10.2021, 13:15 
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  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group