Segfault при изменении значений макроса - PullRequest
0 голосов
/ 21 сентября 2018
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#define len 10
#define hi 10

void transpose(double (*matrix)[len][hi]);

int main() {
  srand(time(NULL));
  double (*matrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
  double delimo, delitel;
  for(int i = 0; i < len; i++){
    for(int j = 0; j < hi; j++){
      delimo = rand()%(len * hi);
      delitel = rand()%(len * hi);
      *matrix[i][j] = delimo/++delitel;
      printf(" %5.2lf ", *matrix[i][j]);
    }
    puts("");
  }
  puts("Transpose: ");
    transpose(matrix);
    for(int i = 0; i < len; i++){
      for(int j = 0; j < hi; j++){
        printf(" %5.2lf ", *matrix[i][j]);
      }
      puts("");
    }
   free(matrix);

}

void transpose(double (*matrix)[len][hi]){
  double (*Tmatrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
  for(int i = 0; i < len; i++){
    for(int j = 0; j < hi; j++){
      *Tmatrix[i][j] = *matrix[j][i];
    }
  }
  for(int i = 0; i < len; i++){
    for(int j = 0; j < hi; j++){
      *matrix[i][j] = *Tmatrix[i][j];
    }
  }
  free(Tmatrix);
}

Задача состоит в том, чтобы выделить двумерный массив, а затем заставить функцию транспонировать его и скопировать транспонированную матрицу в исходную с помощью одного вызова функции.Размеры матрицы задаются макросами, и они также используются в нескольких циклах и при выделении двух матриц.Однако по какой-то странной причине есть ошибка, если я решу их изменить.Единственное, что никогда не разбивалось, это когда len = hi = 10.В любом другом случае программа имеет средний или выше среднего шанс на сбой.

Ответы [ 3 ]

0 голосов
/ 21 сентября 2018

Вы пытаетесь транспонировать матрицу вместо , что проблематично.Действительно, транспонирование неквадратной матрицы дает матрицу другой размерности.Поэтому вы будете непреднамеренно записывать в память, к которой у вас нет доступа, потому что вы пытаетесь разместить свою транспонированную матрицу в массив неверного измерения.

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

0 голосов
/ 22 сентября 2018

Код, показанный в вопросе, дает мою сборку Valgrind conniptions, потому что он неправильно использует нотацию указателя на матрицу.При автономном запуске (не в Valgrind) он работает, но выходная матрица не является транспонированной входной матрицей, поскольку к данным не был получен правильный доступ.Это пример фиктивного вывода, который я получаю.Вы можете видеть, что элементы с индексами 0,1 и 1,0 в матрице 'транспонирования' не связаны с элементами в исходной матрице.

  1.24   2.64   0.17   0.49  22.25   4.30   0.71   1.12   1.03   2.31 
  1.39   7.18   0.40   0.44   4.30   0.17   0.62  12.67   0.34   9.10 
  2.85   0.69   3.50   1.58   0.77   0.04   0.26   0.79   0.24   1.59 
 16.00   0.14   0.12   0.56   1.68   0.08   0.69   0.13   2.51   1.74 
  5.50   0.96   0.45   1.00   0.00   0.84   0.97   0.40   2.14   0.67 
  2.00   0.14   1.84   0.88   1.26   0.21   0.70   0.30   1.74   0.60 
  2.04   1.00   0.35   0.12   0.00   0.65   1.21   0.18   0.52   9.70 
  1.19   1.08   0.88   1.71   0.88   0.21   1.74   0.70   0.44   1.23 
  1.38   0.69   0.12   0.14   4.18   3.17   0.06   7.10   8.00   1.52 
  0.16   6.07   0.81   0.49   0.14   1.37   4.00   0.93   0.98   1.48 
Transpose: 
  1.24   1.24   2.64   0.17   0.49  22.25   4.30   0.71   1.12   1.03 
 -2.00   1.39   1.39   2.85  16.00   5.50   2.00   2.04   1.19   1.38 
  0.17   2.85   0.69   0.69   0.14   0.96   0.14   1.00   1.08   0.69 
  0.49  16.00   0.14   0.12   0.12   0.45   1.84   0.35   0.88   0.12 
 22.25   5.50   0.96   0.45   1.00   1.00   0.88   0.12   1.71   0.14 
  4.30   2.00   0.14   1.84   0.88   1.26   1.26   0.00   0.88   4.18 
  0.71   2.04   1.00   0.35   0.12   0.00   0.65   0.65   0.21   3.17 
  1.12   1.19   1.08   0.88   1.71   0.88   0.21   1.74   1.74   0.06 
  1.03   1.38   0.69   0.12   0.14   4.18   3.17   0.06   7.10   7.10 
  2.31   0.16   6.07   0.81   0.49   0.14   1.37   4.00   0.93   0.98 

Приведенный ниже код работает для квадратных матриц.Разница в том, что указатель на матрицу разыменовывается до применения подписки ((*matrix)[i][j]), а не после (*matrix[i][j]).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define len 10
#define hi 10

void transpose(double (*matrix)[len][hi]);

int main(void)
{
    srand(time(NULL));
    double (*matrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
    double delimo, delitel;
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            delimo = rand() % (len * hi);
            delitel = rand() % (len * hi);
            (*matrix)[i][j] = delimo / ++delitel;
            printf(" %5.2lf ", (*matrix)[i][j]);
        }
        puts("");
    }
    puts("Transpose: ");
    transpose(matrix);
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            printf(" %5.2lf ", (*matrix)[i][j]);
        }
        puts("");
    }
    free(matrix);
}

void transpose(double (*matrix)[len][hi])
{
    double (*Tmatrix)[len][hi] = (double (*)[len][hi])malloc(sizeof(double[len][hi]));
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            (*Tmatrix)[i][j] = (*matrix)[j][i];
        }
    }
    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < hi; j++)
        {
            (*matrix)[i][j] = (*Tmatrix)[i][j];
        }
    }
    free(Tmatrix);
}

Пример вывода:

  0.98   0.90   0.16   0.08   0.48   1.71   0.53   0.24   2.28   1.79 
  0.73   0.36   2.00   3.27   0.29   1.25  19.40   1.60   0.56   0.00 
  3.00  10.50   1.81   1.56   1.11   0.78   1.53   0.71   1.27   0.93 
  2.10   0.56   2.34   1.48   0.81   2.16   0.47   0.16   7.62   0.91 
  0.93   2.48   0.15   0.71   1.09   0.73   0.58   0.48   1.13   0.99 
  0.59   0.72   8.75   2.19  61.00   1.41   2.08   0.83   0.65   0.16 
  0.42   1.13   0.85   1.00   3.00   0.55   0.33   1.67   0.44   0.69 
  0.08   1.17   0.25   0.92   1.04   0.17   1.77   1.95   0.50   0.90 
  2.28   0.35   0.41   1.27   0.80   3.36   0.29   0.13   3.88   0.39 
  0.64   0.50   0.40   0.15   0.45   0.78   0.31   1.48   1.50   1.06 
Transpose: 
  0.98   0.73   3.00   2.10   0.93   0.59   0.42   0.08   2.28   0.64 
  0.90   0.36  10.50   0.56   2.48   0.72   1.13   1.17   0.35   0.50 
  0.16   2.00   1.81   2.34   0.15   8.75   0.85   0.25   0.41   0.40 
  0.08   3.27   1.56   1.48   0.71   2.19   1.00   0.92   1.27   0.15 
  0.48   0.29   1.11   0.81   1.09  61.00   3.00   1.04   0.80   0.45 
  1.71   1.25   0.78   2.16   0.73   1.41   0.55   0.17   3.36   0.78 
  0.53  19.40   1.53   0.47   0.58   2.08   0.33   1.77   0.29   0.31 
  0.24   1.60   0.71   0.16   0.48   0.83   1.67   1.95   0.13   1.48 
  2.28   0.56   1.27   7.62   1.13   0.65   0.44   0.50   3.88   1.50 
  1.79   0.00   0.93   0.91   0.99   0.16   0.69   0.90   0.39   1.06 

Вы не можете транспонировать неквадратную матрицу на месте.Если в качестве входных данных используется матрица n x m, транспонирование представляет собой матрицу m x n.Вероятно, проще всего выделить матрицу транспонирования, в которой вы разместите нетранспонированную матрицу и передать обе матрицы функции транспонирования.Обратите внимание на использование *matrix для передачи указателя на матрицу в качестве матрицы функции.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

void transpose(int rows, int cols, double matrix[rows][cols], double result[cols][rows]);
void print_matrix(const char *tag, int rows, int cols, double matrix[rows][cols]);

int main(void)
{
    srand(time(NULL));
    int cols = 10;
    int rows =  8;
    double (*matrix)[rows][cols] = malloc(sizeof(double[rows][cols]));
    double (*result)[cols][rows] = malloc(sizeof(double[cols][rows]));
    if (matrix == 0 || result == 0)
    {
        fprintf(stderr, "failed to allocate memory\n");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            double delimo = rand() % (rows * cols);
            double delitel = rand() % (rows * cols) + 1;
            (*matrix)[i][j] = delimo / delitel;
        }
    }

    print_matrix("original", rows, cols, *matrix);
    transpose(rows, cols, *matrix, *result);
    print_matrix("transpose", cols, rows, *result);

    free(matrix);
    free(result);
    return 0;
}

void print_matrix(const char *tag, int rows, int cols, double matrix[rows][cols])
{
    printf("%s (%dx%d):\n", tag, rows, cols);
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
            printf(" %5.2f ", matrix[i][j]);
        putchar('\n');
    }
}

void transpose(int rows, int cols, double matrix[rows][cols], double result[cols][rows])
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            result[j][i] = matrix[i][j];
        }
    }
}

Пример вывода:

original (8x10):
  0.84   0.92   0.18   1.97   4.54  31.00   1.59   0.11   0.35   0.07 
  0.96   3.19   1.00   4.86   3.25   3.50   2.65   1.07   0.24   0.77 
  6.00   0.13   0.40   1.04   0.99   0.88   1.24   0.67   3.07  12.00 
  1.89   0.48   0.72   0.55   0.26   0.64   0.55   0.09   0.30   0.98 
  0.51   0.86   0.85   0.33   1.44   0.89   2.38   2.21   0.27   2.12 
  6.40   1.71   2.83   1.61   0.76   0.13   0.81   1.48   1.13   0.51 
  0.79   0.69   0.57   1.10   1.00   1.31   0.68   1.95   1.42   0.46 
  0.00   0.43   1.64   0.88   1.03   0.14   0.35   1.78   0.86   2.82 
transpose (10x8):
  0.84   0.96   6.00   1.89   0.51   6.40   0.79   0.00 
  0.92   3.19   0.13   0.48   0.86   1.71   0.69   0.43 
  0.18   1.00   0.40   0.72   0.85   2.83   0.57   1.64 
  1.97   4.86   1.04   0.55   0.33   1.61   1.10   0.88 
  4.54   3.25   0.99   0.26   1.44   0.76   1.00   1.03 
 31.00   3.50   0.88   0.64   0.89   0.13   1.31   0.14 
  1.59   2.65   1.24   0.55   2.38   0.81   0.68   0.35 
  0.11   1.07   0.67   0.09   2.21   1.48   1.95   1.78 
  0.35   0.24   3.07   0.30   0.27   1.13   1.42   0.86 
  0.07   0.77  12.00   0.98   2.12   0.51   0.46   2.82 

Valgrind дает обоим из них чистый счет здоровья.Исходный код заставил Valgrind сообщать о множестве ошибок, таких как:

==33404== Signal 11 being dropped from thread 0's queue

Мне пришлось убить этот запуск из другого окна терминала.

0 голосов
/ 21 сентября 2018

Вы слишком стараетесь.Просто удалите все элементы динамического размещения, а также указатели.Динамическое распределение памяти совершенно бесполезно в вашем случае.

Вот, пожалуйста:

#define len 2
#define hi 2

void transpose(double matrix[len][hi]);

int main() {
  srand(time(NULL));
  double matrix[len][hi];
  double delimo, delitel;
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      delimo = rand() % (len * hi);
      delitel = rand() % (len * hi);
      matrix[i][j] = delimo / ++delitel;
      printf(" %5.2lf ", matrix[i][j]);
    }
    puts("");
  }
  puts("Transpose: ");
  transpose(matrix);
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      printf(" %5.2lf ", matrix[i][j]);
    }
    puts("");
  }
}

void transpose (double matrix[len][hi]) {
  double Tmatrix[len][hi];
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      Tmatrix[i][j] = matrix[j][i];
    }
  }
  for (int i = 0; i < len; i++) {
    for (int j = 0; j < hi; j++) {
      matrix[i][j] = Tmatrix[i][j];
    }
  }
}

Отказ от ответственности:

  • это работает только для квадратных матриц.
  • возможны другие проблемы
...