【问题标题】:Why am I getting junk values despite using calloc()?尽管使用 calloc(),为什么我得到垃圾值?
【发布时间】:2023-04-04 10:40:01
【问题描述】:

我想知道为什么前两个元素总是非零。我不知道我还能如何描述这个问题,但这不允许我发布这个问题,所以我正在写这个。不确定这是否可行。

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

#define SIZE 3

void printMatrix(int **m)
{
    for (int i = 0; i < SIZE; i++) {
        for (int j = 0; j < SIZE; j++)
            printf("%d ", m[i][j]);
        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    int **matrix;

    matrix = (int **) calloc(sizeof(int), SIZE);

    for (int i = 0; i < SIZE; ++i)
        matrix[i] = (int *) calloc(sizeof(int), SIZE);

    printf("%s\n", "Matrix initialized.");

    printMatrix(matrix);

    return 0;
}

输出:

Matrix initialized.
1371548192 32653 0 
0 0 0 
0 0 0

【问题讨论】:

  • 您能否将您对 calloc 的第一次调用更新为 matrix = (int **) calloc(sizeof(int*), SIZE); 并让我知道是否有任何变化?
  • 是的,在我将其更改为sizeof(int *) 后它起作用了。我意识到在我的系统上它将是 8,而 sizeof(int) 是 4。

标签: c matrix dynamic-memory-allocation


【解决方案1】:

你没有分配足够的内存:

matrix = (int **) calloc(sizeof(int), SIZE);

在这里,您尝试创建一个包含 3 个int * 的数组,但您只为 3 个int 分配空间。如果指针大于系统上的 int(很可能是这样),则在为每一行创建数组时写入数组的末尾。在分配的内存结束后写入会调用undefined behavior

由于您正在创建一个 int * 数组,因此将其用于每个元素的大小:

matrix = calloc(sizeof(int *), SIZE);

另外,不要转换malloc/realloc/calloc的返回值,因为如果您忘记#include &lt;stdlib.h&gt;,这会掩盖错误

【讨论】:

    【解决方案2】:

    参考手册将calloc 描述为:

    void* calloc (size_t num, size_t size);
    

    所以,calloc 首先采用 num 的元素,然后是 size 的特定元素

    试试:

    matrix = (int **) calloc(SIZE, sizeof(int *));
    

    【讨论】:

    • 请注意,问题不在于参数的顺序(最终无关紧要,尽管您建议使用正确的顺序很好),而是sizeof(int)
    • @Acorn 我在某些方面同意你的看法。线索是为下一个指针分配内存,而不是值的类型。指针的大小取决于系统设置,这就是我们得到未定义行为的原因。
    【解决方案3】:

    代码使用calloc(sizeof(int), SIZE),但结构中的实际数据类型是int *,导致在某些系统上内存分配不足(我的给int大小为4,int *大小为8)。

    这是一个重写建议(我们将在 calloc 调用中根据其标头交换大小参数):

    int main(int argc, char const *argv[]) {
        int **matrix;
    
        if (!(matrix = calloc(SIZE, sizeof(*matrix)))) { 
            fprintf(stderr, "calloc failed");
            return 1;
        }
    
        for (int i = 0; i < SIZE; ++i) {
             if (!(matrix[i] = calloc(SIZE, sizeof(*(matrix[i]))))) {
                fprintf(stderr, "calloc failed");
                return 1;
            }
        }
    
        printf("%s\n", "Matrix initialized.");
        printMatrix(matrix);
        return 0;
    }
    

    在这里,我们分别使用*matrix*matrix[i] 而不是hard coding 类型int *int。如果我们需要在某些时候进行类型调整,这可以帮助我们避免错误并寻找更改代码的位置。

    我们还通过测试指针是否为非空来检查calloc 是否成功。不这样做可能会由于未定义的行为而引入难以发现的错误。

    注意Do I cast the result of malloc?

    【讨论】:

    • sizeof(*matrix[i]) 让我有点害怕。是sizeof( (*matrix)[i]) 还是sizeof( * (matrix[i]))?当然,规则规定了其中之一,但sizeof *(matrix[i]) 毫无疑问p = malloc(sizeof *(p) * n) 成语。
    猜你喜欢
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多