简体   繁体   English

在 C 中使用 Malloc/Free 进行内存泄漏

[英]Memory leak using Malloc/Free in C

I've been reading up on the use of pointers, and allocating memory for embedded projects.我一直在阅读指针的使用以及为嵌入式项目分配内存。 I must admit, that i perhaps don't understand it fully, as i can't seem to figure where my problem lies.我必须承认,我可能不完全理解它,因为我似乎无法弄清楚我的问题出在哪里。

My two functions are supposed to take 4 float values, and return 16 bytes, that represent these, in order to transfer them through SPI.我的两个函数应该采用 4 个浮点值,并返回 16 个字节,代表这些值,以便通过 SPI 传输它们。 It works great, but only for a minute, before the program crashes and my SPI and I2C dies, lol.它工作得很好,但只有一分钟,然后程序崩溃,我的 SPI 和 I2C 死了,哈哈。

Here are the functions:以下是功能:

/*Function that wraps a float value, by allocating memory and casting pointers. 
Returns 4 bytes that represents input float value f.*/
typedef char byte;

byte* floatToByteArray(float f)
{
    byte* ret = malloc(4 * sizeof(byte));
    unsigned int asInt = *((int*)&f);
    
    int i;
    for (i = 0; i < 4; i++) {
        ret[i] = (asInt >> 8 * i) & 0xFF;
    }

    return ret;
    memset(ret, 0, 4 * sizeof(byte)); //Clear allocated memory, to avoid taking all memory
    free(ret);
}

/*Takes a list of 4 quaternions, and wraps every quaternion in 4 bytes.
Returns a 16 element byte list for SPI transfer, that effectively contains the 4 quaternions*/
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
    uint8_t m;
    uint8_t n;
    uint8_t k = 0; 
    
    for (m = 0; m < 4; m++)
    {   
        for (n = 0; n < 4; n++)
        {
            byte* asBytes = floatToByteArray(Quaternion[m]);
            buff[n+4*k] = asBytes[n];
        }   
        k++;
    }
}

The error message i receive after is the following, in the disassembly window of Atmel Studio我收到的错误消息如下,在 Atmel Studio 的反汇编窗口中

Atmel studio screenshot爱特梅尔工作室截图

You might drop all the dynamic memory allocation completely.您可能会完全放弃所有动态内存分配。

void floatToByteArray(float f, byte buf[4])
{
    memcpy(buf, &f, sizeof(f));
}

void wrap_quaternions(float Quaternion[4], int8_t *buff)
{   
    for (int i = 0; i < 4; i++)
    {   
        floatToByteArray(Quaternion[i], &buf[4*i]);
    }
}

With this approach you do not need to care about freeing allocated memory after use.使用这种方法,您无需关心在使用后释放分配的内存。 It is also much more efficient because dynamic memory allocation is rather expensive.它也更有效,因为动态内存分配相当昂贵。

Gerhardh is correct, return prevent the memory from being released. Gerhardh 是正确的, return防止内存被释放。

If you need to return 4 bytes, you might check if your environment can return a uint32_t or something like that.如果您需要返回 4 个字节,您可以检查您的环境是否可以返回 uint32_t 或类似的内容。

As already mentioned, the lines below return ret;如前所述,下面的行return ret; are never executed.永远不会被执行。 And anyway if you want to return allocated memory in a function (what is fine) you can't free it in the function itself but it has to be freed by the caller when it isn't needed anymore.无论如何,如果你想在一个函数中返回分配的内存(这很好),你不能在函数本身中释放它,但是当它不再需要时,它必须由调用者释放。 So your calling function should look like所以你的调用函数应该看起来像

/*Takes a list of 4 quaternions, and wraps every quaternion in 4 bytes.
Returns a 16 element byte list for SPI transfer, that effectively contains the 4 quaternions*/
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
    uint8_t m;
    uint8_t n;
    uint8_t k = 0; 
    
    for (m = 0; m < 4; m++)
    {   
        byte* asBytes = floatToByteArray(Quaternion[m]); // no need it to call for every n
        for (n = 0; n < 4; n++)
        {
             buff[n+4*k] = asBytes[n];
        }
        free(asBytes);  // asBytes is no longer needed and can be free()d 
        k++; 
    }
}

regarding:关于:

buff[n+4*k] = asBytes[n];

This results in:这导致:

buff[0] << asBytes[0]  // from first call to `byte* floatToByteArray(float f)`
buff[4] << asBytes[1]  // from second call to `byte* floatToByteArray(float f)`

buff[8] << asBytes[2]  // from third call to `byte* floatToByteArray(float f)`

buff[12] << asBytes[3] // from forth call to `byte* floatToByteArray(float f)`

most of the above problem can be fixed by using memcpy() to copy the 4 bytes from asBytes[] to buff[] similar to:上述大部分问题可以通过使用memcpy()将 4 个字节从asBytes[]复制到buff[]类似于:

memcpy( &buff[ n*4 ], asBytes, 4 );

Of course, there is also the consideration: Is the length of a float , on your hardware/compiler actually 4 bytes.当然,还有一个考虑:是一个float的长度,在您的硬件/编译器上实际上是 4 个字节。

'magic' numbers are numbers with no basis. “魔术”数字是没有基础的数字。 'magic' numbers make the code much more difficult to understand, debug, etc. IE 4. Suggest using something like: length = sizeof( float ); 'magic' 数字使代码更难理解、调试等。 IE 4. 建议使用类似的东西: length = sizeof( float ); then using length everywhere that 4 is currently being used, except for the number of entries in the Quaternion[] array.然后在当前使用4任何地方使用length ,除了Quaternion[]数组中的条目Quaternion[] for that 'magic' number, strongly suggest the statement: #define arraySize 4 be early in your code.对于那个“神奇”数字,强烈建议声明: #define arraySize 4在代码的早期。 Then using arraySize each time the code references the number of elements in the array然后每次代码引用数组中的元素数时使用arraySize

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

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