我正在处理微处理器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。
我已经坚持了几个小时的问题,任何帮助表示赞赏。
答案 0 :(得分:1)
STM32F1的核心是Cortex-M3。这个QA here指出虽然Cortex-M3允许未对齐的字访问以获得简单的指令not all instructions support unaligned access。在您的情况下,C编译器使用的指令不支持带有double的未对齐地址。
请注意
标准库malloc
返回一个“适当对齐的指针,以便可以将其指定给指向具有基本对齐要求的任何类型对象的指针,然后用于访问分配给空间的对象或此类对象的数组“ (C11 7.22.3)
虽然指针可能会转换为另一个指针,“如果生成的指针未针对引用的类型正确对齐,则行为未定义” (C11 6.3.2.3p7)。
因此,程序的行为已经在这些行中未定义
int *hoho = mem_malloc(sizeof(int));
double *hoho = mem_malloc(sizeof(double));
如果返回的指针未分别与int
和double
正确对齐。
要修复代码,请更改它以便始终返回正确对齐的指针。官方ARM编译器maintain an 8-byte aligned heap。