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

标签 c arrays memory file-io printf

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


fprintf() 删除数组元素

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

注意:由于函数头参数的原因,我不得不将这个普通的 (char** array) 转换为这个函数参数中的常量。我们的教授给了我们头文件,我们无法更改其中的任何内容。

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

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

pgmWrite() - Showing array is still fine

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

After fprintf() executes, element 3 memory is wiped out.

运行时,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];

代码header[r]表示访问headArr指向的空间中存储的第r指针。但是由于该空间只有 4 个字节大,所以您实际上是在注销到远处的狂野蓝色。

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

headArr 的整个方法从一开始就存在缺陷:即使您实际上编写了正确的代码来实现您正在尝试的内容,您也会将指针返回到空间中,该空间在函数返回。

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

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

阅读 C FAQ - arrays and pointers也可能有用。

关于C - fprintf() & printf() 删除数组元素内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33724173/

相关文章:

c - 从 main 返回指针

c - 这是为数组分配内存的好方法吗? (C)

arrays - 在向量存在之前用 'end' 创建索引数组

c - 如何从C中的动态数组中的二进制文件读取数据

.net - 如何制作 .NET 应用程序 "large address aware"?

c - fscanf 和二维整数数组

c - 32 位机器上的 Malloc 和大小

c++ - 将字符串列表转换为 C 样式数组

c - 使用 GOTO 时 StackFrames 会受到怎样的影响?

ios - 在 NSTimer 中调用 AFNetworking 导致严重的内存泄漏