C - fprintf() & printf() 删除数组元素内存



我对C编程还很陌生,但fprintf()&printf()的行为很奇怪,我很困惑为什么——我需要一些帮助来理解和诊断这个问题。


fprintf()删除数组元素

首先,我将一个填充的malloc分配的四元素char**数组传递到一个简单的函数中,该函数将写入一个文件,数组中的所有内容都显示正常,并且所有四个元素都包含正确的数据。main()中的函数调用如下所示。我的数组是

注意由于函数头参数的原因,我不得不将此正常(char** array)强制转换为此函数参数中的常量。我们的教授给了我们头文件,我们不能更改其中的任何内容

pgmWrite((const char**) header, (const int**) matrix, 
    rowPixels, colPixels, outFile);

接下来,在调试器执行fprintf()&printf()函数,显示数组的屏幕截图中仍然填充了我的4个元素。

pgmWrite()-显示阵列仍然良好

在执行fprintf()之后,观察数组的第4个元素。

在执行fprintf()之后,元件3的存储器被擦除。

运行时,printf()执行数组的打印,打印内容与调试器中显示的内容完全相同,在第3个元素处结束。通常在该位置不打印任何内容,或者在极少数情况下打印垃圾字符。printf()的行为与fprintf()的工作方式完全相同。


我在这里不知所措,伙计们,请帮我理解我做错了什么。我只能提供这两张截图,基于我是一名新会员。我会尽力提供尽可能多的信息。非常感谢。这是我的程序的简化版本。请记住,教授给了我们函数声明,并告诉我们不能更改它们。所以,我必须利用我在这里所拥有的。此外,由于这是fileIO,您需要找到一个*.pgm文件来测试它。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define rowsInHeader 4
#define maxSizeHeadRow 200
int ** pgmRead( char **header, int *numRows, int *numCols, FILE *in  ){
// INITIALIZING
char *headArr[rowsInHeader][maxSizeHeadRow];
char buffer[100];
int r = 0;
fpos_t pos;
// CREATE: Header
while (r < 4){
// IF: Row in pgm file header lists the dimensions of matrix
if (r == 2){
// CURSOR: Saving pointer location in file (see notes in header for method reference)
fgetpos(in, &pos);
// ASSIGN: Dereference column and row pointers from file
fscanf(in, "%d %d", numCols, numRows);
// CURSOR: Moving back to saved pointer location (see notes in header for method reference)
fsetpos(in, &pos);
}
// ASSIGN: Copying header row into array
fgets(buffer, maxSizeHeadRow, in);
strcpy((char*)headArr[r], buffer);
// POINTER: Reference pointer to headArr[]
header[r] = (char*)headArr[r];
// TRAVERSE: To next row in file
r++;
}
// NOTE: Placeholder for return type
return 0;
}
int pgmWrite( const char **header, const int **pixels, int numRows, int numCols, FILE *out ){
// INITIALIZING
int i = 0;
// WRITE: Header
for (i = 0; i < rowsInHeader; i++){
    fprintf(out, "%s", header[i]);
    printf("%s", header[i]);
}
return 0;
}
int main(int argc, char *argv[]){
char **header = (char**)malloc(rowsInHeader * sizeof(char));
FILE *inFile = fopen("smallFile.pgm", "r");
FILE *outFile = fopen("TestPicture.ascii.pgm", "w");;
int rowPixels = 0;
int colPixels = 0;
int **matrix = NULL;
// READ & WRITE
matrix = pgmRead(header, &rowPixels, &colPixels, inFile);
pgmWrite((const char**)header, (const int**)matrix, rowPixels, colPixels, outFile);
// FINALIZING
fclose(inFile);
free(header);
return 0;
}

您没有正确分配数组。此行:

char **header = (char**)malloc(rowsInHeader * sizeof(char));

使得header指向大小为4字节的存储器的未初始化区域。

然后在你的PGM函数中,你写道:

header[r] = (char*)headArr[r];

代码CCD_ 12表示访问存储在CCD_ 14所指向的空间中的第CCD_。但由于这个空间只有4个字节大,你实际上是在向那边的狂野蓝色划去。

此外,(char *)headArr[r]也是一个错误。如果您没有使用强制转换,编译器会警告您这个错误。您应该避免在代码中使用强制转换,尤其是使用它们来消除警告。你对编译器说"嘘,我知道我在做什么",而实际上你不知道自己在做什么。

headArr的整个方法从一开始就有缺陷:即使你真的写了正确的代码来实现你所尝试的,你也会将指针返回到空间中,当函数返回时,这些指针会被释放。

基本上,整个pgmRead函数都是一团糟,从头开始会更容易。但这一次,请仔细考虑何时何地分配内存,以及表达式的类型,并且不要使用强制类型转换。让pgmRead函数来完成所有的分配。

(不幸的是,根据您的描述,您似乎必须使用类型转换来调用pgmWrite函数,因为它的签名有错误。const int **应该是const int * const *,对于const char **也是如此。我建议您相应地更改pgmWrite的签名,使程序正常工作,然后一旦一切正常,就返回到您被迫使用的损坏版本使用。)

阅读C常见问题解答-数组和指针可能也很有用。

最新更新