我正在研究微处理器stm32f103上的一些C代码 . 由于从堆中分配内存不稳定,我不鼓励使用C库函数 malloc()
和 free()
等 . 相反,我想在编译期间提前声明一大块静态内存,并重新分配内存以适应我的伪动态内存分配目的 . 我的新malloc实现在我的计算机上进行测试时运行正常,但是当我为malloc执行双数据类型时,它在stm32上崩溃了 .
这是我的malloc实现 . 我知道这不是一个真正的动态内存分配,但我只是练习使用指针 .
pk_malloc.c
#include "pk_malloc.h"
char pool[RESERVE];
void* alloc[RESERVE];
void mem_init()
{
for (int i = 0; i != RESERVE; i++)
{
alloc[i] = NULL;
}
}
void* mem_malloc(size_t size)
{
if (size > 0)
{
for (int i = 0; i != RESERVE; i++)
{
if (alloc[i] == NULL)
{
int end;
for (end = i; end != RESERVE; end++)
{
if (alloc[end] != NULL || end - i == size + 1)
{
break;
}
}
if (end - i == size + 1)
{
for (int k = i + 1; k != end; k++)
{
alloc[k] = &pool[k];
}
return alloc[i + 1];
}
}
}
}
return NULL;
}
void* mem_realloc(void* mem, size_t new_size)
{
if (mem == NULL)
{
return mem_malloc(new_size);
}
int old_size = 0;
void** alloc_t = &alloc[(char*)(mem) - pool];
while (*alloc_t != NULL)
{
old_size++;
alloc_t++;
}
if (new_size <= old_size)
{
mem_free((char*)mem + new_size);
return mem;
}
else
{
int i = alloc_t - alloc;
int size = new_size - old_size;
int end;
for (end = i; end != RESERVE; end++)
{
if (alloc[end] != NULL || end - i == size + 1)
{
break;
}
}
if (end - i == size + 1)
{
for (int k = i; k != end - 1; k++)
{
alloc[k] = &pool[k];
}
return alloc[i];
}
else
{
void* realloc_t = mem_malloc(new_size);
if (realloc_t == NULL)
{
return mem;
}
else
{
mem_copy(realloc_t, mem);
mem_free(mem);
return realloc_t;
}
}
}
}
void mem_copy(void* dest, void* source)
{
int dest_index = (char*)(dest) - pool;
int source_index = (char*)(source) - pool;
char* writer = (char*)(source);
while (alloc[source_index] != NULL && alloc[dest_index] != NULL)
{
pool[dest_index] = pool[source_index];
dest_index++;
source_index++;
}
}
void mem_free(void* mem)
{
if (mem != NULL)
{
void** alloc_t = &alloc[(char*)(mem) - pool];
while (*alloc_t != NULL)
{
*alloc_t = NULL;
alloc_t++;
}
}
}
pk_malloc.h
#ifndef _PK_MALLOC
#define _PK_MALLOC
#include <stdlib.h>
#define RESERVE 64
void mem_init();
void* mem_malloc(size_t size);
void* mem_realloc(void* mem, size_t new_size);
void mem_copy(void* dest, void* source);
void mem_free(void* mem);
#endif
main.c中
int main()
{
mem_init();
int* hoho = (int*)(mem_malloc(sizeof(int)));
*hoho = 123;
printf("%d", *hoho);
mem_free(hoho);
}
代码可以在我的计算机上运行,也适用于STM32 . 但是当我将我的数据类型更改为double时:
int main()
{
mem_init();
double* hoho = (double*)(mem_malloc(sizeof(double)));
*hoho = 0.618;
printf("%f", *hoho);
mem_free(hoho);
}
它只适用于我的计算机,而它在STM32上崩溃了 .
我做了一些测试和调试,我发现这行有效,指针不是NULL,它有一个有效的地址 .
double* hoho = (double*)(mem_malloc(sizeof(double)));
然而这条线坠毁了 .
*hoho = 0.618;
经过更多测试,我发现占用4个字节以上的任何数据类型都以相同的方式崩溃,包括 long long
等 .
奇怪的是,我做了一些用户定义的结构,包含大量的 int
, float
数据类型等,它们肯定占用超过4个字节,代码在STM32上工作正常 .
struct ABC
{
int a;
float b;
};
这条线没有问题 .
struct ABC* hoho = (struct ABC*)(mem_malloc(sizeof(struct ABC)));
可以分配变量 hoho
,并且可以在我的计算机和STM32上轻松访问其成员 .
请注意,所有代码都适用于我的笔记本电脑,大多数数据类型也适用于STM32 .
我已经坚持了几个小时的问题,任何帮助赞赏 .
1 回答
STM32F1的核心是Cortex-M3 . 这个QA here指出虽然Cortex-M3允许未对齐的字访问以获得简单的指令,not all instructions support unaligned access . 在您的情况下,C编译器使用不支持带有double的未对齐地址的指令 .
请注意
标准库
malloc
返回一个指针"suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated" (C11 7.22.3)而指针可以转换为另一个指针,"if the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined" (C11 6.3.2.3p7) .
因此,程序的行为在这些行中尚未定义
如果返回的指针没有分别适合
int
和double
.要修复代码,请更改它以便始终返回正确对齐的指针 . 官方ARM编译器maintain an 8-byte aligned heap .