Испытание ошибки сегментации при создании функций для инициализации и очистки массива mpz_t - PullRequest
0 голосов
/ 02 апреля 2020

Я использую GNU MP для создания массива чисел с множественной точностью. Если я инициализирую, использую и очищу все функции main , она будет работать без ошибок. Я пытался создать вспомогательные функции для управления повторяющимися заданиями: инициализировать массив и очистить массив. К сожалению это не закончилось хорошо, я получаю утечку памяти. Я сделал небольшой пример ниже, воспроизводящий поведение ошибки:

#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

mpz_t *start(int n)
{
  mpz_t *c = malloc(n*sizeof(mpz_t));
  for (int i=0; i<n; i++) mpz_init (c[i]);
  for (int i=0; i<n; i++) mpz_set_ui (c[i], 1);
}

void finish(mpz_t *x, int n)
{
  for (int i=0; i<n; i++) mpz_clear (x[i]);
  free(x);
}

int main(int argc, char *argv[])
{
  int n = 10;
  mpz_t *c = start(n);
  finish(c, n);
  return 0;
}

Результат запуска программы:

Segmentation fault (core dumped)

Ниже следует журнал анализа Valgrind:

==18807== Memcheck, a memory error detector
==18807== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==18807== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==18807== Command: ./test
==18807== 
==18807== Invalid read of size 4
==18807==    at 0x4887C60: __gmpz_clear (in /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2)
==18807==    by 0x10928B: finish (test.c:14)
==18807==    by 0x1092DF: main (test.c:22)
==18807==  Address 0xa is not stack'd, malloc'd or (recently) free'd
==18807== 
==18807== 
==18807== Process terminating with default action of signal 11 (SIGSEGV)
==18807==  Access not within mapped region at address 0xA
==18807==    at 0x4887C60: __gmpz_clear (in /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2)
==18807==    by 0x10928B: finish (test.c:14)
==18807==    by 0x1092DF: main (test.c:22)
==18807==  If you believe this happened as a result of a stack
==18807==  overflow in your program's main thread (unlikely but
==18807==  possible), you can try to increase the size of the
==18807==  main thread stack using the --main-stacksize= flag.
==18807==  The main thread stack size used in this run was 8388608.
==18807== 
==18807== HEAP SUMMARY:
==18807==     in use at exit: 240 bytes in 11 blocks
==18807==   total heap usage: 11 allocs, 0 frees, 240 bytes allocated
==18807== 
==18807== 240 (160 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==18807==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==18807==    by 0x1091E8: start (test.c:7)
==18807==    by 0x1092CA: main (test.c:21)
==18807== 
==18807== LEAK SUMMARY:
==18807==    definitely lost: 160 bytes in 1 blocks
==18807==    indirectly lost: 80 bytes in 10 blocks
==18807==      possibly lost: 0 bytes in 0 blocks
==18807==    still reachable: 0 bytes in 0 blocks
==18807==         suppressed: 0 bytes in 0 blocks
==18807== 
==18807== For lists of detected and suppressed errors, rerun with: -s
==18807== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

Что не так? Как это исправить?

1 Ответ

0 голосов
/ 03 апреля 2020

Выход из конца функции, возвращающей значение (кроме main) без оператора return, является неопределенным поведением.

В вашем примере mpz_t *start(int n) фактически ничего не возвращает, что приводит к UB.

...