我的一个指针在我尊重它之后被改变并影响它。我不明白为什么,特别是因为该函数中的代码多次运行但大部分时间都在运行。这是代码:
typedef struct s_freeList
{
int sSize;
struct s_freeList *next;
struct s_freeList *back;
int *eSize;
} t_freeList;
void *addNode(void *addr, size_t size)
{
t_freeList *freeList;
// Working stuff
freeList = (t_freeList *)addr;
freeList->sSize = size * -1;
freeList->next = ((t_freeList *)g_startAddr)->next;
freeList->back = g_startAddr;
((t_freeList *)g_startAddr)->next->back = freeList;
((t_freeList *)g_startAddr)->next = freeList;
// Not working stuff
printf("addr = %p\nsize = %d\n", addr, (int)size);
freeList->eSize = addr + size - 4;
printf("freelist->esize = %p\n", freeList->eSize);
*(freeList->eSize) = size * -1;
printf("freelist->esize = %p\n\n", freeList->eSize);
return (collapseNodes(addr));
}
以下是地址输出:
addr = 0x1647020
size = 32
freelist->esize = 0x164703c
freelist->esize = 0xffffffe00164703c
答案 0 :(得分:5)
从v
输出中,您将在具有64位指针的平台上运行。每个指针都有大小,重要的是,8个字节的自然对齐,它给出了结构的以下布局(偏移量为十进制):
printf
您正在设置 00 sSize;
04 <padding>
08 *next;
16 *back;
24 *eSize;
32 <total size>
,其中freeList->eSize = addr + size - 4
恰好与size = 32
字段本身的较高部分重叠。
如果您要进行地址算术,请尽可能使用编译器提供的内省工具,例如eSize
和sizeof
。它们可以减少此类错误的发生率,并使代码更具可读性和便携性。
(或者,更好的是,完全避免地址算术)。
答案 1 :(得分:3)
我没有尝试过代码,但这是我认为它发生的事情。以下几行为新节点分配值并将其插入列表中:
// Working stuff
freeList = (t_freeList *)addr;
freeList->sSize = size * -1;
freeList->next = ((t_freeList *)g_startAddr)->next;
freeList->back = g_startAddr;
((t_freeList *)g_startAddr)->next->back = freeList;
((t_freeList *)g_startAddr)->next = freeList;
显然,addr
是指向新插入节点的指针。现在这是有趣的事情:
freeList->eSize = addr + size - 4;
假设size == sizeof(struct s_freeList)
那么你基本上做的是为eSize
分配自己的地址+4个字节!我认为这是因为sizeof(int *)
碰巧是8个字节,而在内存中你的结构可能是这样的:
----------
|sSize | <-- addr
----------
|next |
----------
|back; |
----------
|eSize; | <-- addr + size - 4 probably because sizeof(int *) == 8 bytes.
----------
所以当你这样做时:
*(freeList->eSize) = size * -1;
您正在修改eSize
的值,因为它指向自己!
编辑:我只是在重新编写代码并输出并且atzz说的是正确的时候,你可能正在运行一台64位机器,但是这个想法仍然是一样的,eSize
正在覆盖自己......