首页 文章

C为双指针赋值

提问于
浏览
1

我正在研究微处理器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 等 .

奇怪的是,我做了一些用户定义的结构,包含大量的 intfloat 数据类型等,它们肯定占用超过4个字节,代码在STM32上工作正常 .

struct ABC
{
    int a;
    float b;
};

这条线没有问题 .

struct ABC* hoho = (struct ABC*)(mem_malloc(sizeof(struct ABC)));

可以分配变量 hoho ,并且可以在我的计算机和STM32上轻松访问其成员 .

请注意,所有代码都适用于我的笔记本电脑,大多数数据类型也适用于STM32 .

我已经坚持了几个小时的问题,任何帮助赞赏 .

1 回答

  • 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 *hoho = mem_malloc(sizeof(int));
    double *hoho = mem_malloc(sizeof(double));
    

    如果返回的指针没有分别适合 intdouble .

    要修复代码,请更改它以便始终返回正确对齐的指针 . 官方ARM编译器maintain an 8-byte aligned heap .

相关问题