【问题标题】:weird double pointer updating memory location奇怪的双指针更新内存位置
【发布时间】:2018-03-30 16:24:48
【问题描述】:

我正在运行以下代码来存储二维方阵。代码读取每一行,按空间分割元素并将它们存储到矩阵的相应单元格中。

输入格式:

第一行包含一个整数n,表示矩阵中的行数和列数。 接下来的行表示矩阵的行,每行包含用空格分隔的整数来描述列。

用于测试的示例输入/输入

5
11 2 4 2 3
4 5 6 -1 0
10 8 -12 8 7
1 2 4 -2 5
10 -2 1 0 2

计划:

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

    }
}

int main(){
    int size,length;
    int **matrix,j;
    char *buff=malloc(1000),*token;    
    fgets(buff,1000,stdin);
    sscanf(buff,"%d",&size);
    matrix=malloc(sizeof(int)*size);

    for(int i=0;i<size;i++){

        //Allocating memory for all the cells in ith row
        matrix[i]=malloc(sizeof(int)*size);    
        buff='\0';
        buff=malloc(1000);
        fgets(buff,1000,stdin);
        length=strlen(buff);    
        if ((buff[length-1])=='\n'){
            buff[length-1]='\0';
        }

        j=0;
        token=strtok(buff," ");
        while(token){
            matrix[i][j]=atoi(token);
            token=strtok(NULL," ");
            j++;
        }
        printf("\n");
        printMatrix(i+1,matrix);


    }
    return 0;    
}

收到的输出

11 

11 2 
4 5 

11 2 4 
4 5 6 
10 8 -12 

11 2 4 2 
4 5 6 -1 
10 8 -12 8 
1 2 4 -2 


869149824 22073 4 2 3 
4 5 6 -1 0 
10 8 -12 8 7 
1 2 4 -2 5 
10 -2 1 0 2 

但是,在第 4 次迭代之后,我得到的垃圾值是 869149824 22073。我不明白第一行是如何被修改的。

我知道我可能犯了一个愚蠢的错误,但我已经花了很长时间弄清楚这里缺少什么。我将不胜感激。

【问题讨论】:

  • matrix=malloc(sizeof(int)*size)... 如果sizeof(int) != sizeof(int *)(就像它通常在 64 位系统上一样)会发生什么?
  • matrix=malloc(sizeof(int*)*size);
  • 为什么要为buff动态分配内存?特别是因为您在分配方面有很多问题(覆盖指针和内存泄漏)。
  • 一个好的成语是var = malloc((sizeof *var) * size);
  • @Someprogrammerdude 谢谢!也许你应该把它写成一个解决方案。我没有意识到 int 和 int* 的大小在 64 位系统上是不同的。

标签: c memory garbage double-pointer


【解决方案1】:

我借此机会编辑和清理了您的程序,您的垃圾打印问题如前所述是由您的内存管理引起的。

这是您的程序的更新版本。

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

void printMatrix(int size, int i, int **matrix) {
    printf("\n");

    for (int y = 0; y <= i; y++) {
        for (int x = 0; x < size; x++) {
            printf("%d ", matrix[y][x]);
        }
        printf("\n");
    }
}

int main() {

    setvbuf(stdout, NULL, _IONBF, 0); // turn of buffering of stdout for debug.

    int size;
    int **matrix, j;

    char buff[1000], *token;
    fgets(buff, 1000, stdin);
    buff[strcspn(buff, "\r\n")] = '\0';
    sscanf(buff, "%d", &size);

    // allocate matrix
    matrix = malloc(sizeof(int*) * size);
    for (int i = 0; i < size; i++) {
        matrix[i] = malloc(sizeof(int) * size);
    }

    for (int i = 0; i < size; i++) {
        fgets(buff, 1000, stdin);
        buff[strcspn(buff, "\r\n")] = '\0';
        j = 0;
        token = strtok(buff, " ");
        while (token) {
            matrix[i][j] = atoi(token);
            token = strtok(NULL, " ");
            j++;
        }
        printMatrix(size, i, matrix);
    }
    return 0;
}

主要区别在于:

  • 静态分配buff
  • 在进入扫描循环之前分配所有需要的内存。
  • 将打印功能改为逐行打印矩阵。

【讨论】:

  • 您能解释一下为什么使用scanf 比fgets 更好吗?据我所知,scanf 存在很多问题,例如缓冲区溢出、处理用户响应输入的方式(如何限制或检测用户是否键入了 page down、return 或一些奇怪的键)。
  • 你是对的,我会编辑我的答案,处理尾随新行的更好方法可能是: fgets(buff, 1000, stdin); buff[strcspn(buff, "\r\n")] = '\0';
  • strcspn() 计算从“stopset”(“\r\n”)匹配的任何字符之前的字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多