«Нарушение доступа при записи» после использования malloc () внутри функции - PullRequest
1 голос
/ 01 апреля 2019

Задача

У меня есть пользовательская структура для 2D матриц. Я использую эту структуру внутри функции для инициализации 2D-матрицы, где каждое значение элемента установлено на 0. У меня также есть другая функция для печати матрицы на терминал (для целей отладки).

Когда я пишу структуру и функции внутри main.c, они работают. Проблема в том, что когда я помещаю их в отдельный файл и вызываю их из этого файла, я получаю сообщение об ошибке во время выполнения: Exception thrown: write access violation.

В моей программе 3 файла: main.c, my_lib.h, my_lib.c. Структура хранится внутри my_lib.h, а функция находится в my_lib.c. Внутри main.h

Я использую Windows 10 и кодирование в Visual Studio 2017 v15.9.10

выход

Программа компилируется, но выдает ошибку времени выполнения Exception thrown: write access violation enter image description here

Edit:

Ну, похоже, это была моя вина, что это происходило.

На самом деле я пытался запустить этот код на своем рабочем компьютере. Я написал оригинальный код на моем персональном компьютере, где работала версия main.c, my_lib.h & my_lib.c. Затем я скопировал папку, над которой я работал, и попытался продолжить на моем рабочем компьютере. Оба моих компьютера работают под управлением ОС Windows 10 и имеют одинаковую версию VS 2017.

На моем персональном компьютере обозреватель решений был похож на:

enter image description here

Но на моем рабочем компьютере решение открылось как:

enter image description here

Все, включая иерархию папок, одинаково на обоих компьютерах. Кажется, копирование папки проекта не очень хорошая идея.

Когда я создал новый проект C на своем рабочем компьютере и добавил my_lib.c и my_lib.h вручную, все работало.

Но мне все еще любопытно, почему я получаю ошибку исключения ... И как я могу исправить эту проблему копирования без создания нового проекта в VS?

Код

Просто main.c (Работы)

main.c

#include <stdio.h>

typedef struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows
}Matrix;

Matrix* make_matrix(int n_rows, int n_cols);
void print_matrix(Matrix* m);

int main() {

    Matrix* m1 = make_matrix(2, 5);

    print_matrix(m1);

    return 0;
}


// CREATE A MATRIX WITH N_ROWS AND N_COLUMNS AND INITIALIZE EACH VALUE AS 0
Matrix* make_matrix(int n_rows, int n_cols) {
    Matrix* matrix = malloc(sizeof(Matrix));
    matrix->rows = n_rows;
    matrix->cols = n_cols;
    double** data = malloc(sizeof(double*) * n_rows);
    for (int x = 0; x < n_rows; x++) {
        data[x] = calloc(n_cols, sizeof(double));
    }
    matrix->data = data;
    return matrix;
}

// PRINT GIVEN MATRIX TO COMMAND LINE
void print_matrix(Matrix* m) {
    for (int x = 0; x < m->rows; x++) {
        for (int y = 0; y < m->cols; y++) {
            printf("%f", m->data[x][y]);
            printf("|");
        }
        printf("\n");
    }
}

main.c & функция в отдельных файлах (исключение)

main.c

#include "my_lib.h"
int main(){
        // Create a 2 by 5 matrix & then print it to terminal
        Matrix* m1 = make_matrix(2, 5);
        print_matrix(m1);
        return 0;
}

my_lib.h

#pragma once

// Our custom 2D matrix struct
typedef struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows
}Matrix;

Matrix* make_matrix(int n_rows, int n_cols);
void print_matrix(Matrix* m);

my_lib.c

#include "my_lib.h"
#include <stdio.h>

// CREATE A MATRIX WITH N_ROWS AND N_COLUMNS AND INITIALIZE EACH VALUE AS 0
Matrix* make_matrix(int n_rows, int n_cols) {
    Matrix* matrix = malloc(sizeof(Matrix));
    matrix->rows = n_rows;
    matrix->cols = n_cols;
    double** data = malloc(sizeof(double*) * n_rows);
    for (int x = 0; x < n_rows; x++) {
        data[x] = calloc(n_cols, sizeof(double));
    }
    matrix->data = data;
    return matrix;
}

// PRINT GIVEN MATRIX TO COMMAND LINE
void print_matrix(Matrix* m) {
    for (int x = 0; x < m->rows; x++) {
        for (int y = 0; y < m->cols; y++) {
            printf("%f", m->data[x][y]);
            printf("|");
        }
        printf("\n");
    }
}

1 Ответ

2 голосов
/ 01 апреля 2019

Причина, по которой вы получаете сбой, вовсе не связана с тем, что в вашем проекте есть один или два файла .c, а потому, что вы забыли включить <stdlib.h> в my_lib.c.

Это вызывает следующие предупреждения триггеров:

my_lib.c (8): предупреждение C4013: «malloc» не определено; при условии внешнего возврат int
my_lib.c (13): предупреждение C4013: 'calloc' не определено; предполагая, что extern возвращает int
my_lib.c (13): предупреждение C4047: '=': 'double *' отличается уровнем косвенности от 'int'
my_lib.c (8): предупреждение C4047: «инициализация»: «Матрица *» отличается уровни косвенности от 'int'
my_lib.c (11): предупреждение C4047: 'initializing': 'double **' отличается уровнем косвенности от 'INT'

С 32-битной сборкой вам это не сойдет, поскольку размер int совпадает с размером указателя.

С другой стороны, если вы строите свою программу как 64-битную программу, предупреждения становятся действительно актуальными, потому что теперь указатели имеют ширину 64 бита, но поскольку компилятор предполагает, что malloc и т. Д. Возвращают int s, все запутано до.

На самом деле эти предупреждения следует рассматривать как ошибки.

Здесь вы решаете, хотите ли вы 32- или 64-битную сборку:

enter image description here

Добавьте #include <stdlib.h> здесь, в my_lib.c:

#include "my_lib.h"
#include <stdlib.h>   // <<<<<<<<<<<<<
#include <stdio.h>


// CREATE A MATRIX WITH N_ROWS AND N_COLUMNS AND INITIALIZE EACH VALUE AS 0
Matrix* make_matrix(int n_rows, int n_cols) {
  Matrix* matrix = malloc(sizeof(Matrix));
  ...
...