我有一个很长的程序,我正在努力缩短它。我经常编写二维文件数组,但我在整个程序中重复此过程数十次,因此我尝试将其编写为函数以减少我的错误并使代码更短且更易于阅读。
我正在修改从 Allocate memory 2d array in function C 获得的示例但用 FILE 数组来代替。
我已经可以在 main 中轻松分配 2D 文件数组,但同样,我想将其作为函数来执行:
#include <stdio.h>
#include <stdlib.h>
void allocate_mem(FILE**** arr, const int n, const int m) {
arr = malloc(n*m*sizeof(FILE));
for(int i=0; i<n; i++) {
arr[i] = malloc(m*sizeof(FILE));
for (unsigned int j = 0; j < m; j++) {
char filename[64];
sprintf(filename,"tmp_%d_%d.txt",i,j);
*arr[i][j] = fopen(filename,"w");
fprintf(*arr[i][j],"blah %d %d\n",i,j);
}
}
}
void deallocate_mem(FILE**** arr, const int n, const int m){
for (int i = 0; i < n; i++) {
for (unsigned int j = 0; j < m; j++) {
fclose(*arr[i][j]);
}
free((*arr)[i]);
}
free(*arr);
}
int main() {
FILE ***array;
allocate_mem(&array,5,3);
deallocate_mem(&array,5,3);
return 0;
}
我已经尝试了几乎所有可以想到的(无论如何对我来说)方法,但我不断从 valgrind 中得到这样的错误:
==16192== HEAP SUMMARY:
==16192== in use at exit: 4,440 bytes in 3 blocks
==16192== total heap usage: 3 allocs, 0 frees, 4,440 bytes allocated
==16192==
==16192== Searching for pointers to 3 not-freed blocks
==16192== Checked 70,808 bytes
==16192==
==16192== 552 bytes in 1 blocks are still reachable in loss record 1 of 3
==16192== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192== by 0x4EA711C: __fopen_internal (iofopen.c:69)
==16192== by 0x40080C: allocate_mem (create_file_array.c:11)
==16192== by 0x400951: main (create_file_array.c:29)
==16192==
==16192== 648 bytes in 1 blocks are still reachable in loss record 2 of 3
==16192== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192== by 0x4007AC: allocate_mem (create_file_array.c:7)
==16192== by 0x400951: main (create_file_array.c:29)
==16192==
==16192== 3,240 bytes in 1 blocks are still reachable in loss record 3 of 3
==16192== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192== by 0x400761: allocate_mem (create_file_array.c:5)
==16192== by 0x400951: main (create_file_array.c:29)
==16192==
==16192== LEAK SUMMARY:
==16192== definitely lost: 0 bytes in 0 blocks
==16192== indirectly lost: 0 bytes in 0 blocks
==16192== possibly lost: 0 bytes in 0 blocks
==16192== still reachable: 4,440 bytes in 3 blocks
==16192== suppressed: 0 bytes in 0 blocks
==16192==
==16192== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==16192==
==16192== 1 errors in context 1 of 2:
==16192== Invalid write of size 8
==16192== at 0x40080D: allocate_mem (create_file_array.c:11)
==16192== by 0x400951: main (create_file_array.c:29)
==16192== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==16192==
==16192==
==16192== 1 errors in context 2 of 2:
==16192== Use of uninitialised value of size 8
==16192== at 0x40080D: allocate_mem (create_file_array.c:11)
==16192== by 0x400951: main (create_file_array.c:29)
==16192== Uninitialised value was created by a heap allocation
==16192== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16192== by 0x4007AC: allocate_mem (create_file_array.c:7)
==16192== by 0x400951: main (create_file_array.c:29)
==16192==
==16192== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
create_file_array.c
如何让 allocate_mem 和 deallocate_mem 工作?
最佳答案
您应该忘记您曾经听说过三颗星或四颗星。与酒店相比,C 编程使用的是逆系统:星级越多,代码质量越差。
You don't even want a pointer-to-pointer-to... You want a 2D array.
话虽这么说,请注意这并不是那么简单,因为您想要数组的类型是 FILE*
。大多数想要成为资深程序员的人都会失败,并建议使用多个 for 循环和多个 malloc 调用进行一些废话,以对可怜的无辜堆发起全面攻击。
取而代之的是,从 main() 开始。 为了保持理智,您可能希望您的 main 看起来像这样:
int main (void)
{
file_arr_t* array; // pointer to a 2D array
array = allocate_mem(5,3);
deallocate_mem(array);
return 0;
}
在这种情况下,allocate_mem
函数需要返回一个指向已分配数组的指针。声明数组指针的 C 语法非常糟糕,因此您需要创建一个 typedef 来保持理智。 typedef 远离指针也是不好的做法,因此最好 typedef 一个您想要指向的数组类型:
typedef FILE* file_arr_t[3][5]; // type is an array of 3x5 FILE*
其中 file_arr_t*
将是指向 3x5 FILE 指针数组的指针。唷。
然后你可以将你的函数编写为:
file_arr_t* allocate_mem (size_t x, size_t y)
{
file_arr_t* array = malloc(sizeof(FILE*[x][y]));
(*array)[i][j] = ... // do things with the pointer to array
return array;
}
void deallocate_mem(file_arr_t* array)
{
free(array);
}
<小时/>
编辑
如果您确实需要尺寸在运行时完全动态,恐怕您会陷入一种令人讨厌的语法情况或另一种情况,因为那样您就无法使用 typedef。你最终会得到像这样不可读的东西:
// turning messy, avoid writing code like this.
void allocate_mem (size_t x, size_t y, FILE* (**arr_ptr)[x][y])
{
*arr_ptr = malloc(sizeof(FILE*[x][y]));
(**arr_ptr)[i][j] = something;
}
int main (void)
{
FILE* (*array)[5][3];
allocate_mem(5, 3, &array);
}
在这种情况下,我建议只使用 void*
来代替:
void* allocate_mem (size_t x, size_t y)
{
// omit inner-most dimension on purpose to get clearer access syntax later
FILE* (*array)[y] = malloc(sizeof(FILE*[x][y]));
// now this pointer can be used with intuitive syntax:
array[i][j] = something;
...
return array;
}
int main (void)
{
FILE* (*array)[5][3];
array = allocate_mem(5, 3);
}
关于C编程: Create and write 2D array of files as function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30711985/