Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基本问题:C函数返回指向malloc';ed结构_C_Pointers_Struct - Fatal编程技术网

基本问题:C函数返回指向malloc';ed结构

基本问题:C函数返回指向malloc';ed结构,c,pointers,struct,C,Pointers,Struct,关于C结构和指针 昨天我写了以下代码(试着用记忆记住其中的一部分): 我看到的是:我可以在函数中使用malloced Tile结构,但是一旦我尝试在Main中访问它,我就会从visualstudio中得到一个关于堆的错误(它告诉我,在调用返回后会释放一些内容) 如果我更改它以便在Main中malloc空格,并将指向该空格的指针作为参数传递给loadTile函数(这样函数就不再返回任何内容),那么它确实可以工作,但我相信我也应该能够让loadTile函数malloc空格并返回指向该空格的指针,对吗

关于C结构和指针

昨天我写了以下代码(试着用记忆记住其中的一部分):

我看到的是:我可以在函数中使用malloced Tile结构,但是一旦我尝试在Main中访问它,我就会从visualstudio中得到一个关于堆的错误(它告诉我,在调用返回后会释放一些内容)

如果我更改它以便在Main中malloc空格,并将指向该空格的指针作为参数传递给loadTile函数(这样函数就不再返回任何内容),那么它确实可以工作,但我相信我也应该能够让loadTile函数malloc空格并返回指向该空格的指针,对吗


谢谢

您显示的代码看起来正常,错误一定在省略的代码中。

您显示的代码看起来正常,错误一定在省略的代码中。

无论您遇到什么问题,都不在本问题中显示的代码中。在返回指针之前,请确保您没有敲击它。

无论您遇到什么问题,它都不在本问题中显示的代码中。在返回指针之前,请确保没有敲击它。

这应该可以正常工作。。。这可能只是VisualStudio发出的一个警告,即您正在释放一个指针,而不是在malloced中释放的指针。

这应该可以正常工作。。。可能只是来自VisualStudio的一个警告,即您正在释放一个与malloced不同的函数中的指针。

您尝试执行的操作没有问题,或者至少从这里的代码中没有问题。但是,我担心这一行:

unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
这不是真的,除非你也在某处把它给骗了:

Tile* tmpResult = malloc(sizeof(Tile));
tmpResult->iTime = malloc(sizeof(short) * n);
您需要在清理时释放它:

free(tmpTile->iTime);
free(tmpTile);

你想做的事情没有错,或者至少从这里的代码来看没有错。但是,我担心这一行:

unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
这不是真的,除非你也在某处把它给骗了:

Tile* tmpResult = malloc(sizeof(Tile));
tmpResult->iTime = malloc(sizeof(short) * n);
您需要在清理时释放它:

free(tmpTile->iTime);
free(tmpTile);

从技术上讲,您的代码将在C编译器上运行。但是,在函数内部动态分配并将指针返回到分配的数据是造成内存泄漏的一种很好的方法,因此这是非常糟糕的编程实践。更好的方法是在调用者中分配内存(本例中为main)。分配内存的代码单元应与释放内存的代码单元相同


顺便说一句,如果这是一个Windows程序,main()必须声明为返回int,否则代码将无法在C编译器上编译。

从技术上讲,您的代码将在C编译器上运行。但是,在函数内部动态分配并将指针返回到分配的数据是造成内存泄漏的一种很好的方法,因此这是非常糟糕的编程实践。更好的方法是在调用者中分配内存(本例中为main)。分配内存的代码单元应与释放内存的代码单元相同


顺便说一句,如果这是一个Windows程序,main()必须声明为返回int,否则代码将无法在C编译器上编译。

您可能是在不拥有的内存上编写的。我想在这一部分:

// do things that set values to the Tile entity
您正在这样做:

tmpResult->iFrames = n;

for (i = 0 ; i < n ; ++n)
{
  tmpResult->iTime [i] = <some value>;
}
在给它写信之前。这使得释放对象更加复杂:

free (tile->iTime);
free (tile);
或者,执行以下操作:

typedef struct {
  unsigned short int iFrames;
  unsigned short int iTime [1]; // array with elements [0..x] holding the timing for each frame
} Tile;
马洛克是这样的:

 tile = malloc (sizeof (Tile) + sizeof (short int) * (n - 1)); // -1 since Tile already has one int defined.
而for循环保持不变:

for (i = 0 ; i < n ; ++n)
{
  tmpResult->iTime [i] = <some value>;
}

因为您只分配了一块内存,而不是两块。这是因为C(和C++)不在数组上执行范围检查。

您可能是在不拥有的内存上进行写操作。我想在这一部分:

// do things that set values to the Tile entity
您正在这样做:

tmpResult->iFrames = n;

for (i = 0 ; i < n ; ++n)
{
  tmpResult->iTime [i] = <some value>;
}
在给它写信之前。这使得释放对象更加复杂:

free (tile->iTime);
free (tile);
或者,执行以下操作:

typedef struct {
  unsigned short int iFrames;
  unsigned short int iTime [1]; // array with elements [0..x] holding the timing for each frame
} Tile;
马洛克是这样的:

 tile = malloc (sizeof (Tile) + sizeof (short int) * (n - 1)); // -1 since Tile already has one int defined.
而for循环保持不变:

for (i = 0 ; i < n ; ++n)
{
  tmpResult->iTime [i] = <some value>;
}

因为您只分配了一块内存,而不是两块。这是因为C(和C++)不在数组上进行范围检查。

您的代码在我能接受的范围内进行了尽可能小的更改,对我来说是可行的:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  unsigned short int iFrames;
  unsigned short int* iTime;
} Tile;

Tile *loadTile(char* sFile) {
  Tile *tmpResult = malloc(sizeof *tmpResult);
  if (!tmpResult) return NULL;

  /* do things that set values to the Tile entity */
  /* note that iTime is uninitialized */
  tmpResult->iFrames = 42;

  (void)sFile; /* used parameter */
  return tmpResult;
}

int main(void) {
  Tile* tmpTile;
  tmpTile = loadTile("tile1.dat");
  if (!tmpTile) return 1;

  printf("value: %d\n", tmpTile->iFrames);

  free(tmpTile);
  return 0;
}
#包括
#包括
类型定义结构{
无符号短整数帧;
无符号短整数*iTime;
}瓷砖;
平铺*加载平铺(char*sFile){
瓷砖*tmpResult=malloc(尺寸*tmpResult);
如果(!tmpResult)返回NULL;
/*执行为平铺实体设置值的操作*/
/*请注意,iTime未初始化*/
tmpResult->iFrames=42;
(void)sFile;/*使用的参数*/
返回tmpResult;
}
内部主(空){
瓦片*tPtile;
tmpTile=负载瓦(“tile1.dat”);
如果(!tmpTile)返回1;
printf(“值:%d\n”,tOptile->iFrames);
免费(tmpTile);
返回0;
}

您的代码对我来说很有用,只要我能接受的改动很少:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  unsigned short int iFrames;
  unsigned short int* iTime;
} Tile;

Tile *loadTile(char* sFile) {
  Tile *tmpResult = malloc(sizeof *tmpResult);
  if (!tmpResult) return NULL;

  /* do things that set values to the Tile entity */
  /* note that iTime is uninitialized */
  tmpResult->iFrames = 42;

  (void)sFile; /* used parameter */
  return tmpResult;
}

int main(void) {
  Tile* tmpTile;
  tmpTile = loadTile("tile1.dat");
  if (!tmpTile) return 1;

  printf("value: %d\n", tmpTile->iFrames);

  free(tmpTile);
  return 0;
}
#包括
#包括
类型定义结构{
无符号短整数帧;
无符号短整数*iTime;
}瓷砖;
平铺*加载平铺(char*sFile){
瓷砖*tmpResult=malloc(尺寸*tmpResult);
如果(!tmpResult)返回NULL;
/*执行为平铺实体设置值的操作*/
/*请注意,iTime未初始化*/
tmpResult->iFrames=42;
(void)sFile;/*使用的参数*/
返回tmpResult;
}
内部主(空){
瓦片*tPtile;
tmpTile=负载瓦(“tile1.dat”);
如果(!tmpTile)返回1;
printf(“值:%d\n”,tOptile->iFrames);
免费(tmpTile);
返回0;
}

void main
。。。Raaaarrrrggggghhhhhhhhh请向我们展示
void main
中存在错误的代码部分。。。Raaaarrrrggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh。定义
foo*make_foo()
free_foo
是C中
foo
构造/初始化和销毁的惯用方法。@larsmans我想我们在这里说的是同样的事情。为了减少耦合,您应该大致像这两个示例中那样:在我看来,好像您推荐了
Tile*p=malloc(sizeof(Tile));初始瓦片(p)
main
@larsmans中,tha没有任何问题