【问题标题】:C: Memory allocation issuesC:内存分配问题
【发布时间】:2021-05-04 09:35:40
【问题描述】:

我在 C 中遇到了(我认为)内存重新分配的问题。该程序旨在运行时,当调用 fopen(array, &num); 时,它将首先从文件中检索数组中的元素数量并将其放置在 num 中,为给定的数组指针重新分配内存,为其提供足够的空间来正确存储文件的内容,然后将值复制到该数组中。这似乎在 fopen 函数中仍然有效(由“标记 1”显示),但在此之外不起作用(由“标记 2”显示),而是似乎喷出随机内存垃圾。任何帮助表示赞赏(包括代码和格式化我布局不佳的问题)。

//main.c
void Rtest(){

  char num;
  struct individual *array;
  array = (struct individual *) malloc(sizeof(struct individual));

  openf(array, &num);

  printf("%d\n", num);

  for (int i = 0; i < num; i++) {printf("%s\n", array[i].name);} //mark 2

  free(array);

}
//fil.h
struct individual {
    char name[32];
    char stats[7];
    char role;
    char roles[13];
};

void openf(struct individual *array, char *num){

  FILE *fp;

  fp = fopen("save.bin", "rb");
  fread(num, 1, sizeof(char), fp);
  array = (struct individual *)realloc(array, *num * sizeof(struct individual));
  printf("%d\n", sizeof(*array));
  fread(array, *num, sizeof(struct individual), fp);
  for (int i = 0; i < *num; i++) {printf("%s\n", array[i].name);} //mark 1

  fclose(fp);

}

文件内容:

03 43 61 72 6C 73 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 055 06 0 300 0 05 06 0 08 0 06 07 08 09 0A 0B 0C 43 61 72 6C 73 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 43 61 72 6C 73 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 05 06 08 00 01 02 03 04 05 06 07 08 09 0A 0B 0C

【问题讨论】:

  • openf 中,代码array = (struct individual *)realloc....openf调用者 没有任何意义,除了可能(实际上很可能)悬空的指针值是传入这个函数。调用者Rtestarray 的原始值仍然存在,但现在不再有效;因此“悬空”。顺便说一句,为什么 numchar ?我的意思是,它可以工作,但非常有限。而且我还认为您停止假设您的所有 IO 都正常工作。这是一种糟糕的做法。
  • @WhozCraig num 是一个字符,因为我有点傻。那么解决方案是将其分成两部分,在 Rtest 中重新分配内存吗?
  • 如果意图是openf 可能会更改该指针的值,并且您希望该更改反映回调用者,那么您可以设计一种方法来做到这一点。使用函数的其他未使用的返回值,或通过地址传递原始指针(指向指针的指针,并在更改指向的指针时在openf 中取消引用),都是该场景的常见解决方案。

标签: arrays c file memory-management structure


【解决方案1】:

当你想改变函数内部的参数时,你需要传递一个指向它的指针。 例如,在Rtest 中,您声明了一个名为num 的字符。它没有值,你把它发送到openf,但是你实际上把指针发送到num,因为你想改变它的值,你做对了,确实openf成功地改变了num的值。

但是array 呢?好吧,你在Rtest 上声明了它并为它分配了内存空间,这一切都是正确的。然后,您想将它作为指针发送到Rtest,以便函数可以更改它。 array 是“指向结构个体的指针”类型的变量。这没关系,但是如果您想在Rtest 中更改它,那么您需要为该变量发送一个指针。因此,您需要一个“指向结构个体的指针”。请注意,变量名称是从之前复制的,我只是添加了“POINTER TO”

我确定你知道什么是指针指针,你需要做的就是使用:

openf(&array, &num);

当然还有修改openf,所以它会使用新的“指针指向指针”,类似这样:

void openf(struct individual **array, char *num){

  FILE *fp;

  fp = fopen("save.bin", "rb");
  fread(num, 1, sizeof(char), fp);
  *array = (struct individual **)realloc(*array, *num * sizeof(struct individual));
  printf("%d\n", sizeof(**array));
  fread(*array, *num, sizeof(struct individual), fp);
  for (int i = 0; i < *num; i++) {printf("%s\n", (*array)[i].name);} //mark 1

  fclose(fp);

}

当我在我的机器上运行此代码以及Rtest 并提供save.bin 时,我得到以下输出:

53
Carlson
Carlson
Carlson
3
Carlson
Carlson
Carlson

编辑: 正如@WhozCraig 在 cmets 中提到的那样,您可以使用未使用的函数返回值并返回“新”数组的指针,这可能是一种更好的做事方式,而不是“指针指针”的东西,但这取决于你。

【讨论】:

  • 我认为这里有一个错误,这不应该是*array = (struct individual **)realloc(... 吗? Yu 想更改内存地址array 上的数据,例如*array,而不是内存位置本身array。对吗?
  • 您提供的解决方案似乎不起作用。复制此代码后,它不再在标记 1 处打印,而是崩溃了。
  • @DanielFarrell 是的,你是绝对正确的。我编辑了我的原始帖子,谢谢。约翰,你可以在我更改丹尼尔发现的内容后再次尝试复制代码。
  • @GalBirka 非常抱歉,但我还是崩溃了。此代码是否适用于您的机器,因为我开始怀疑这可能是我的设置问题。
  • 我无法在我的机器上运行代码,因为我没有二进制文件。我注意到 malloc 函数的另一个问题,因此您可以先尝试复制粘贴我的原始代码并尝试。如果它不起作用,您可以尝试提供一些详细信息,例如您遇到的错误或崩溃的行。最后,您可以尝试上传您的二进制文件并在此处链接,我将在我的机器中查看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-21
  • 2016-06-19
  • 2011-01-07
  • 2011-03-18
相关资源
最近更新 更多