【问题标题】:Basic C Matrix segmentation memory allocation基本 C 矩阵分段内存分配
【发布时间】:2015-10-16 00:45:53
【问题描述】:

我试图通过终端运行这个程序,但出现了这个错误。 “分段错误:11”

我想知道为什么。这个程序所做的是,它读取一个 .ppm 文件并将其信息保存在 Pixel 类型的矩阵变量中,因此,PPM 文件基本上由以下部分组成:第一行默认为“P3”,第二行矩阵的大小,第三行是像素属性可能的最大值,其他行将有 3 个最大值为 255 的整数,因此对于矩阵的每个成员,将有一个像素 R、G、B。 我在函数 save_image 中尝试做的事情,首先识别我们是否正在处理 ppm 文件(检查第一行中是否有 P3),然后读取矩阵的行数和列数,然后创建一个新的使用 malloc 函数的矩阵,然后它将文件行中的数据保存到变量 myImg 的 .r 和 .g 和 .b 中。 我对调试/编程非常陌生,所以如果信息不足,我很抱歉,但我已尽力而为。

#include <stdio.h>
#include <stdlib.h>
typedef struct{
    int r;
    int g;
    int b;
}Pixel;

void save_image(FILE* img, Pixel ** newImg) {
    int i;
    int j;
    int fcount;
    int scount;
    int count;
    int dcc;
    char init[3];
    fscanf(img,"%s",init);
    if(init[0]=='P' && init[1]=='3'){
        printf("worked!\n");
        fscanf(img,"%d %d",&j,&i);
        fscanf(img, "%d",&dcc);
        *newImg = (Pixel*)malloc(sizeof(Pixel) * i);
        for ( count = 0; count < i ; ++count)
        {
            newImg[count] = (Pixel*)malloc(sizeof(Pixel) * j);
        }
        for (fcount = 0; fcount <= i ; ++fcount)
        {
         for (scount = 0; scount <= j; ++scount)
         {
            fscanf(img,"%i %i %i",&newImg[i][j].r,&newImg[i][j].g,&newImg[i][j].b);
         }
        }
    }
    else 
        printf("Type of file not recognized\n");

    fclose(img);
}


int main(int argc, char const *argv[])
{
    FILE* image;
    Pixel myImg;
    Pixel** newImg;
    **newImg = myImg;
    image = fopen(argv[1],"r");
    save_image(image,newImg);
    return 0;
}

【问题讨论】:

  • ppm 文件示例pastebin.com/9vvtqwH5
  • 1) 发布的代码编译不干净。 2) 在访问 argv[0] 之外的任何 argv[] 条目之前,始终检查 argc 的值以确保实际输入了命令行参数。如果未输入,则输出“使用”语句并退出。 3)变量newImg在初始化之前在main()中使用。编译时始终启用所有警告,然后修复警告。 (对于 gcc,至少使用:-Wall -Wextra -pedantic
  • 调用函数:fscanf()时,一定要检查返回值(不是参数值),保证操作成功
  • 命名变量时,使用有意义的名称。 'i' 和 'j' 对于循环计数器可能没问题,但对于 row widthnumber of rows in image 来说毫无意义
  • 强烈建议,为了省去很多麻烦,在 save_image() 函数中声明 newImg 并将结果指针传递回 main() 而不是在 main() 中声明 newImg 并将地址传递给 as save_image() 的参数。因此,这一行:*newImg = (Pixel*)malloc(sizeof(Pixel) * i);(无论如何都不正确)应该是:Pixel **newImg = malloc(sizeof(Pixel*) * i); 在 C 中,不要从 malloc()(和函数族)转换返回值,因为它是 void *,所以可以分配给任何其他指针。

标签: c file memory allocation


【解决方案1】:

程序失败是因为 newImg[] 的初始 malloc 是对 Pixel 大小的一些倍数而不是指向 Pixel 的指针大小的 malloc 以及将指向 newImg 的指针作为参数传递给 save_image 的问题() 功能。请参阅我关于应该在何处定义变量 newImg 以及对 save_image() 函数声明的理想修改的评论

鉴于发布的代码是编写的,它似乎期待“普通”.ppm 文件格式

并且发布的代码不允许文件中包含任何嵌入的 cmets

鉴于对 .ppm 文件格式的描述:

格式定义如下。您可以使用 libnetpbm C 子程序库方便准确地读取和解释格式。

一个 PPM 文件由一系列的一个或多个 PPM 图像组成。图像之前、之后或之间没有数据、分隔符或填充。

每个 PPM 图像包含以下内容:

A "magic number" for identifying the file type. A ppm image's magic number is the two characters "P6".
Whitespace (blanks, TABs, CRs, LFs).
A width, formatted as ASCII characters in decimal.
Whitespace.
A height, again in ASCII decimal.
Whitespace.
The maximum color value (Maxval), again in ASCII decimal. Must be less than 65536 and more than zero.
A single whitespace character (usually a newline).
A raster of Height rows, in order from top to bottom. Each row consists of Width pixels, in order from left to right. Each pixel is a triplet of red, green, and blue samples, in that order. Each sample is represented in pure binary by either 1 or 2 bytes. If the Maxval is less than 256, it is 1 byte. Otherwise, it is 2 bytes. The most significant byte is first.

A row of an image is horizontal. A column is vertical. The pixels in the image are square and contiguous.

In the raster, the sample values are "nonlinear." They are proportional to the intensity of the ITU-R Recommendation BT.709 red, green, and blue in the pixel, adjusted by the BT.709 gamma transfer function. (That transfer function specifies a gamma number of 2.2 and has a linear section for small intensities). A value of Maxval for all three samples represents CIE D65 white and the most intense color in the color universe of which the image is part (the color universe is all the colors in all images to which this image might be compared).

ITU-R Recommendation BT.709 is a renaming of the former CCIR Recommendation 709. When CCIR was absorbed into its parent organization, the ITU, ca. 2000, the standard was renamed. This document once referred to the standard as CIE Rec. 709, but it isn't clear now that CIE ever sponsored such a standard.

Note that another popular color space is the newer sRGB. A common variation on PPM is to substitute this color space for the one specified.

Note that a common variation on the PPM format is to have the sample values be "linear," i.e. as specified above except without the gamma adjustment. pnmgamma takes such a PPM variant as input and produces a true PPM as output. 

以“#”开头的字符串可能是 cmets,与 PBM 相同。

请注意,您可以使用 pamdepth 在每个样本 1 个字节的格式和每个样本 2 个字节的格式之间进行转换。

此处提及的所有字符均以 ASCII 编码。 “换行符”是指在 ASCII 中称为换行符或 LF 的字符。 “空白”字符是空格、CR、LF、TAB、VT 或 FF(即 ANSI 标准 C isspace() 函数所称的空白)。 纯PPM

实际上还有另一种相当罕见的 PPM 格式版本:“普通”PPM 格式。上述格式通常被认为是正常格式,称为“原始”PPM 格式。有关普通格式和原始格式之间的关系以及如何使用它们的一些评论,请参阅 pbm。

普通格式的区别是:

There is exactly one image in a file.
The magic number is P3 instead of P6.
Each sample in the raster is represented as an ASCII decimal number (of arbitrary size).
Each sample in the raster has white space before and after it. There must be at least one character of white space between any two samples, but there is no maximum. There is no particular separation of one pixel from another -- just the required separation between the blue sample of one pixel from the red sample of the next pixel.
No line should be longer than 70 characters. 

以下是这种格式的小图像示例。

 P3
 # feep.ppm
 4 4
15
 0  0  0    0  0  0    0  0  0   15  0 15
 0  0  0    0 15  7    0  0  0    0  0  0
 0  0  0    0  0  0    0 15  7    0  0  0
15  0 15    0  0  0    0  0  0    0  0  0

每行末尾都有一个换行符。

读取这种格式的程序应该尽可能宽松,接受任何看起来像 PPM 图像的东西。

【讨论】:

  • 很好,我能够根据你所说的更正我的代码。
猜你喜欢
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 2021-12-08
相关资源
最近更新 更多