【问题标题】:"Write Acces Violation" After Using malloc() Inside a Function在函数中使用 malloc() 后出现“写访问冲突”
【发布时间】:2023-03-26 12:59:01
【问题描述】:

问题

我有二维矩阵的自定义结构。我在一个函数中使用这个结构来初始化一个二维矩阵,其中每个元素值都设置为 0。我还有另一个函数可以将矩阵打印到终端(用于调试目的)。

当我在main.c 中编写结构和函数时,它们可以工作。问题是当我将它们放在一个单独的文件中并从该文件中调用它们时,我得到一个运行时错误:Exception thrown: write access violation

在我的程序中,我有 3 个文件:main.cmy_lib.hmy_lib.c。结构存储在my_lib.h 中,函数在my_lib.c 中。里面main.h

我在 Visual Studio 2017 v15.9.10 中使用 Windows 10 和编码

输出

程序编译但出现运行时错误Exception thrown: write access violation

编辑:

嗯,发生这种情况似乎是我自己的错。

实际上,我试图在我的工作计算机上运行此代码。我已经在我的个人计算机上编写了原始代码,main.cmy_lib.hmy_lib.c 版本正在运行。然后我复制了我正在处理的文件夹并尝试在我的工作计算机上继续。我的两台电脑都在 Windows 10 操作系统上运行,并且都具有相同版本的 VS 2017。

在我的个人电脑上,解决方案资源管理器是这样的:

但在我的工作计算机上,解决方案打开为:

包括文件夹层次结构在内的所有内容在两台计算机上都是相同的。看来,复制项目文件夹不是个好主意。

当我在我的工作计算机上创建一个新的 C 项目并手动添加 my_lib.cmy_lib.h 时,一切正常。

但我仍然很好奇为什么会出现异常错误...以及如何在不在 VS 中创建新项目的情况下纠正这个复制问题?

代码

只需 main.c(有效)

ma​​in.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 & 函数在单独的文件中(抛出异常)

ma​​in.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");
    }
}

【问题讨论】:

  • @xing 他们都在同一个文件夹中
  • 它们都是同一个文件夹并不重要。在 main() 调用 make_matrix() 时,它还不知道 make_matrix 的定义。如果在 my_lib.h 中添加以下行会发生什么?矩阵* make_matrix(int n_rows, int n_cols);
  • 为了更好地衡量,您还应该包含&lt;stdlib.h&gt; 以获得m/calloc 的正确原型。
  • 如果您改用标准 C 编译器,这甚至无法编译。不过嘿嘿,C99发布才20年,或许我们应该给MS更多的时间去适应。
  • @OguzCanbek 你忘了#include &lt;stdlib.h&gt;。你没有收到任何编译器警告吗?

标签: c exception multidimensional-array struct malloc


【解决方案1】:

导致崩溃的原因与您的项目中有一个或两个 .c 文件这一事实完全无关,而是因为您忘记在 my_lib.c 中包含 &lt;stdlib.h&gt;

这会触发以下警告:

my_lib.c(8) : 警告 C4013: 'malloc' 未定义;假设外部 返回 int
my_lib.c(13): 警告 C4013: 'calloc' undefined; 假设 extern 返回 int
my_lib.c(13): 警告 C4047: '=': “double *”与“int”的间接级别不同
my_lib.c(8): 警告 C4047: 'initializing': 'Matrix *' 不同 来自“int”
my_lib.c(11) 的间接级别:警告 C4047: 'initializing': 'double **' 的间接级别不同 'int'

您可以在 32 位构建中摆脱它,因为 int 的大小与指针的大小相同。

另一方面,如果您将程序构建为 64 位程序,则警告变得非常相关,因为现在指针是 64 位宽,但是编译器假定 malloc 等返回 ints(32 位值),一切都搞砸了。

实际上这些警告应该被视为错误。

在这里您决定是需要 32 位还是 64 位版本:

my_lib.c中添加#include &lt;stdlib.h&gt;

#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));
  ...

【讨论】:

  • 感谢您的回答以及关于 32 位和 64 位程序的详细解释 :) 我还有另一个新手问题:我是否应该将 &lt;stdlib.h&gt; 也包括在我的 main.c 中,或者因为我已经加到my_lib.c了,不需要吗?
  • @OguzCanbek 不,没有必要,除非你在main.c 中使用stdlib.h 中声明的函数之一,目前还不是这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 2018-03-02
  • 2023-03-27
相关资源
最近更新 更多