LINUX.ORG.RU

Как сортировать массив в Vala?

 ,


2

2

Я конечно просто туплю, но никак не могу найти пример использования функции qsort_with_data

Пока сделал так(всё работает):

static int greater (void* a, void* b)
{
    int arg1 = * (int*)a;
    int arg2 = * (int*)b;

    if (arg1 < arg2) return 1;
    if (arg1 > arg2) return -1;
    return 0;
}

void some_func(int[] copy_input)
{
    Posix.qsort(copy_input, copy_input.length, sizeof(int), greater);
    ....
}
Хотелось бы использовать вместо Posix.qsort, функцию qsort_with_data.

Попробовал использовать её так:

static int greater_int (int arg1, int arg2)
{
    if (arg1 < arg2) return 1;
    if (arg1 > arg2) return -1;
    return 0;
}
void some_func(int[] copy_input)
{
    qsort_with_data<int>(copy_input, sizeof(int), greater_int);
    ....
}

Получаю

/usr/share/vala-0.36/vapi/glib-2.0.vapi:5714:11: runtime error: load of misaligned address 0x60200000ea74 for type 'const <unknown> *', which requires 8 byte alignment
0x60200000ea74: note: pointer points here
  0e 00 00 00 0e 00 00 00  0e 00 00 00 0e 00 00 00  03 00 00 00 00 00 00 02  10 00 00 00 01 00 00 54
              ^ 
/usr/share/vala-0.36/vapi/glib-2.0.vapi:5714:11: runtime error: load of misaligned address 0x60200000ea74 for type 'const <unknown> *', which requires 8 byte alignment
0x60200000ea74: note: pointer points here
  0e 00 00 00 0e 00 00 00  0e 00 00 00 0e 00 00 00  03 00 00 00 00 00 00 02  10 00 00 00 01 00 00 54
Если у кого-то есть опыт использования шаблонной функции qsort_with_data, прошу поделиться простейшим примером.

P.S. на valadoc смотрел, к сожалению именно к этой функции нет примера:

https://valadoc.org/glib-2.0/GLib.qsort_with_data.html

Хотя, например, к потокам есть объясняющий пример https://valadoc.org/glib-2.0/GLib.Thread.html

Если используешь лямбду:

qsort_with_data<int>(numbers, sizeof(int), (a, b) => { return a == b ? 0 : a < b ? -1 : 1; });
Если используешь обычную функцию:
qsort_with_data<int>(numbers, sizeof(int), compare);
При этом функция выглядит так:
int compare(int a, int b) {
  if (a > b) return 1;
  if (b > a) return -1;
  return 0;
}
Насколько я понял, у тебе нужна обратная сортировка, в таком случае нужно поменять местами 1 и -1.

Тестовые программы:
void main() {
  int[] numbers = { 10, 30, 1, 8, -5, 7, 666, 12 };
  foreach (int a in numbers) { stdout.printf("%d ", a); }
  stdout.printf("\n");
  qsort_with_data<int>(numbers, sizeof(int), (a, b) => { return a == b ? 0 : a < b ? -1 : 1; });
  foreach (int a in numbers) { stdout.printf("%d ", a); }
  stdout.printf("\n");
}

int compare(int a, int b) {
  if (a > b) return 1;
  if (b > a) return -1;
  return 0;
}

void main() {
  int[] numbers = { 10, 30, 1, 8, -5, 7, 666, 12 };
  foreach (int a in numbers) { stdout.printf("%d ", a); }
  stdout.printf("\n");
  qsort_with_data<int>(numbers, sizeof(int), compare);
  foreach (int a in numbers) { stdout.printf("%d ", a); }
  stdout.printf("\n");
}

CYB3R ★★★★★ ()
Ответ на: комментарий от CYB3R

Спасибо за примеры. Твои примеры работают отдельно хорошо. Когда я вставляю их в свою функцию, то получаю runtime error :(

Просто мистика.

https://github.com/fsb4000/mystic_vala

код это решение простой задачки: https://www.codewars.com/kata/how-green-is-my-valley/train/c

fsb4000 ★★ ()
Ответ на: комментарий от CYB3R

Всё, спасибо за помощь ещё раз.

Это баг в vala или gcc sanitizers.

Все примеры правильные. Всё работает. Но если добавить флаги при компиляции(для незнающих Vala, -X значит что флаги для gcc, а не для valac):

-X -fsanitize=address -X -fsanitize=undefined -X -fsanitize=leak -X -fno-omit-frame-pointer
То падает с runtime error.

Значит либо vala генерит код который делает какой-то UB по мнению gcc sanitizers, либо код нормальный, но есть баг в gcc sanitizers, который по ошибке считает код багованным.

Значит мне придётся использовать Posix.qsort, на эту функцию не ругается gcc sanitizers, а я не готов отказываться от sanitizers при разработке...

Спасибо ещё раз за отклик на возникший вопрос!

fsb4000 ★★ ()
Ответ на: комментарий от CYB3R

Нет, в багзилле бага не нашёл.

Проверил ещё на FreeBSD 11.1 с clang 5.0

Там кроме runtime error ещё такое clang выдал:

SUMMARY: AddressSanitizer: undefined-behavior test.vala.c:68:19
То есть даже конкретную строку в с файле указал которая не понравилась.

Добавил баг сюда: https://bugzilla.gnome.org/show_bug.cgi?id=792534

fsb4000 ★★ ()
Ответ на: комментарий от CYB3R

В багзилле оказывается был этот баг, я неправильно искал(я искал про qsort_with_data, нужно было про шаблоны в общем):

https://bugzilla.gnome.org/show_bug.cgi?id=774713

Так что, чтобы сортировать массив целых чисел нужно либо изменить тип массива и шаблонной функции с int на int?(я проверил, после этого ошибки выдаваемые санитайзерами пропали), либо использовать Posix.qsort

fsb4000 ★★ ()