armv5中c中指针赋值的错误

时间:2014-11-10 12:32:23

标签: c linux arm debian

我在c中有以下代码:

LinkedList
MemAllocLinkedList_add(MemAllocLinkedList self, void* data)
{
    LinkedList newElement = (LinkedList)
            MemoryAllocator_allocate(self->ma, sizeof(struct sLinkedList));

    if (newElement == NULL)
        return NULL; 

    newElement->data = data;  

    newElement->next = NULL; 

    LinkedList listEnd = LinkedList_getLastElement((LinkedList) self);

    listEnd->next = newElement;

    return newElement;
}

char*
MemoryAllocator_allocate(MemoryAllocator* self, int size)
{
    if (((self->currentPtr - self->memoryBlock) + size) <= self->size) {
        char* ptr = self->currentPtr;
        self->currentPtr += size;
        return ptr;
    }
    else{
        printf("MemoryAllocator_allocate: Out of Memory\n");
        return NULL;
    }
}

是LinkedList指向sLinkedList的指针:

struct sLinkedList {
    void* data;
    struct sLinkedList* next;
};

和MemAllocLinkedList指向sMemAllocLinkedList的指针:

struct sMemAllocLinkedList {
    void* data;
    struct sLinkedList* next;
    MemoryAllocator* ma;
};

我有一个程序多次调用这个'MemAllocLinkedList_add'函数没有问题,但有一点,在这个函数中,赋值'listEnd-&gt; next = newElement'用las 16切换前16位,所以没有在listEnd-&gt;下一个975912上,我有-467140594,当我稍后尝试访问该列表的最后一个元素时,会导致SISEGEV错误。

如果我编译它并在具有debian(intel 64bits)和raspberry pi(armv6 32位)的虚拟机上运行它,它可以正常工作。但是,当我尝试使用armv5tej的NanosG20时,我会解释这件事。我使用gcc 4.6。

有人知道为什么会这样吗?

感谢。

编辑:

这是LinkedList_getLastElement:

LinkedList
LinkedList_getLastElement(LinkedList list)
{int i=0;
    while (list->next != NULL) {
        list = list->next; i++;     
    }
    return list;
}

输入MemoryAllocator:

typedef struct {
    char* memoryBlock;
    char* currentPtr;
    int size;
} MemoryAllocator;

此代码来自libiec61850,是针对子电站的标准61850的实现,因此有更多代码无法在此处发布。我只是发布了我收到错误的部分,但就像我说的那样,仅在使用ARMv5的主板上,而不是在VM或Raspberry Pi上。

1 个答案:

答案 0 :(得分:3)

你实际上在所有3个平台上都遇到了同样的问题,只是在Intel和ARMv6上你得到了“看似正常工作”的未定义行为形式。

以下是C标准的相关引用(我必须提交的C99的n1256草案中的6.3.2.3):

  

指向对象或不完整类型的指针可能会转换为指向其他对象的指针   对象或不完整的类型。如果生成的指针未正确对齐   指向类型,行为未定义。

“正确对齐”的概念由平台的ABI定义。在这种情况下,ARM ABI表示thar char需要1字节对齐,而指针需要4字节对齐。由于struct sLinkedList由两个指针组成,因此它必须至少与指针一样严格对齐。

现在,由于MemoryAllocator_allocate每次都将size的内部空闲指针天真递增,因此不能保证它返回的char *比1字节对齐更好,从而转换为到struct sLinkedList *导致3/4可能情况下的未定义行为。由于编译器往往比报复更加务实,而不是nasal demons你得到了未定义的行为“无论硬件对未对齐的加载/存储做什么”解除引用它,这可能是一个对齐错误,返回一些无意义的数据,甚至返回你期望的数据。

解决方案是使MemoryAllocator_allocate始终向上舍入size到最大所需对齐的最大倍数 - 对于ARM ABI,这是8个字节,但如果您确定要< em>从不使用任何64位类型(如doublelong long),你可能可以使用4个字节。