简体   繁体   English

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

[英]Basic question: C function to return pointer to malloc'ed struct

About C structs and pointers... 关于C结构和指针...

Yesterday I wrote sort of the following code (try to memorize parts of it out of my memory): 昨天,我编写了以下代码(试图将部分代码存储在内存中):

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

What I see: I cán use the malloced Tile structure inside the function, but once I try to access it in Main, I get an error from Visual Studio about the heap (which tells me that something is freed after the call is returned). 我所看到的是:我在函数内使用了malloced Tile结构,但是一旦尝试在Main中访问它,就会从Visual Studio中得到有关堆的错误(告诉我在调用返回后释放了某些内容)。

If I change it so that I malloc space in Main, and pass the pointer to this space to the loadTile function as an argument (so that the function does no longer return anything) then it does work but I am confident that I should also be able do let the loadTile function malloc the space and return a pointer to that space right?! 如果我更改它以便在Main中分配空间,并将指向该空间的指针作为参数传递给loadTile函数(以便该函数不再返回任何内容),则它可以工作,但我相信我也应该能够让loadTile函数分配空间并返回指向该空间的指针吗?

Thanks!! 谢谢!!

There's nothing wrong with what you're trying to do, or at least not from the code here. 您尝试执行的操作没有任何问题,或者至少不是来自此处的代码。 However, I'm concerned about this line: 但是,我担心这条线:

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

That isn't true unless you're also mallocing iTime somewhere: 除非您还在某个地方分配了iTime,否则情况并非如此:

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

You will need to free it when you clean up: 清理时需要释放它:

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

You are probably writing over memory you don't own. 您可能正在覆盖您不拥有的内存。 I guess that in this section: 我猜在本节中:

// do things that set values to the Tile entity

you're doing this: 您正在执行此操作:

tmpResult->iFrames = n;

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

which is wrong, you need to allocate separate memory for the array: 这是错误的,您需要为数组分配单独的内存:

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

before writing to it. 在写之前。 This make freeing the object more complex: 这使得释放对象更加复杂:

free (tile->iTime);
free (tile);

Alternatively, do this: 或者,执行以下操作:

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

and malloc like this: 和malloc这样的:

 tile = malloc (sizeof (Tile) + sizeof (short int) * (n - 1)); // -1 since Tile already has one int defined.

and the for loop remains the same: 和for循环保持不变:

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

but freeing the tile is then just: 但释放磁贴只是:

free (tile);

as you've only allocated one chunk of memory, not two. 因为您只分配了一块内存,而不是两个。 This works because C (and C++) does not do range checking on arrays. 之所以可行,是因为C(和C ++)不对数组进行范围检查。

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

Whatever problem you are having, it is not in the code shown in this question. 无论您遇到什么问题,它都不会出现在此问题所示的代码中。 Make sure you are not clobbering the pointer before returning it. 返回指针之前,请确保没有破坏指针。

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

Technically, your code will work on a C compiler. 从技术上讲,您的代码将在C编译器上运行。 However, allocating dynamically inside functions and returning pointers to the allocated data is an excellent way of creating memory leaks - therefore it is very bad programming practice. 但是,在函数内部动态分配并返回指向已分配数据的指针是造成内存泄漏的一种极好的方法-因此,这是非常糟糕的编程习惯。 A better way is to allocate the memory in the caller (main in this case). 更好的方法是在调用方(在这种情况下为main)中分配内存。 The code unit allocating the memory should be the same one that frees it. 分配内存的代码单元应该与释放它的代码单元相同。

Btw if this is a Windows program, main() must be declared to return int, or the code will not compile on a C compiler. 顺便说一句,如果这是Windows程序,则必须声明main()返回int,否则代码将无法在C编译器上编译。

You code, with as little changes as I could live with, works for me: 您编写的代码所做的更改很少,我可以使用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM