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

时间:2011-03-16 14:51:08

标签: c pointers struct

关于C结构和指针......

昨天我写了以下代码(尝试记住部分代码):

    typedef struct {
    unsigned short int iFrames;
    unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame
    } Tile;

    Tile* loadTile(char* sFile)
    {
    // expecting to declare enough space for one complete Tile structure, of which the base memory address is stored in the tmpResult pointer
    Tile* tmpResult = malloc(sizeof(Tile));

    // do things that set values to the Tile entity
    // ...

    // return the pointer for further use
    return tmpResult;
    }

    void main()
    {
    // define a tile pointer and set its value to the returned pointer (this should also be allowed in one row)
// Expected to receive the VALUE of the pointer - i.e. the base memory address at where malloc made space available
    Tile* tmpTile;
    tmpTile = loadTile("tile1.dat");

    // get/set elements of the tile
    // ...

    // free the tile
    free(tmpTile);
    }

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

如果我更改它以便在Main中使用malloc空间,并将指向此空间的指针作为参数传递给loadTile函数(以便该函数不再返回任何内容)那么它确实有效但我相信我还应该能够让loadTile函数malloc空间并返回指向该空间的指针吗?!

谢谢!

7 个答案:

答案 0 :(得分:4)

你正在尝试做什么,或者至少不是来自这里的代码没有错。但是,我关注这一行:

unsigned short int* iTime; // array with elements [0..x] holding the timing for each frame

除非你在某个地方使用iTime进行malloc,否则这不是真的:

Tile* tmpResult = malloc(sizeof(Tile));
tmpResult->iTime = malloc(sizeof(short) * n);

清理时需要释放它:

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

答案 1 :(得分:2)

你可能正在写你不拥有的记忆。我想在本节中:

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

tmpResult->iFrames = n;

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

这是错误的,你需要为数组分配单独的内存:

tmpResult->iTime = malloc (sizeof (short int) * n);
在写信之前

。这使得释放对象更加复杂:

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;

和malloc是这样的:

 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>;
}

但释放瓷砖只是:

free (tile);

因为你只分配了一块内存,而不是两块。这是有效的,因为C(和C ++)不对数组进行范围检查。

答案 2 :(得分:0)

您显示的代码看起来不错,错误必须在省略的代码中。

答案 3 :(得分:0)

无论您遇到什么问题,都不在此问题中显示的代码中。确保在返回之前没有破坏指针。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

从技术上讲,您的代码将适用于C编译器。但是,在函数内部动态分配并返回指向已分配数据的指针是创建内存泄漏的绝佳方法 - 因此编程实践非常糟糕。更好的方法是在调用者中分配内存(在本例中为main)。分配内存的代码单元应该与释放内存的代码单元相同。

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

答案 6 :(得分: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;
}