意外的C结构指针大小行为
我的代码中出现了一些奇怪的行为,这似乎是由于使用了泛型指针造成的,但实际上我完全不确定。我有一个相当标准的结构,如下所示:意外的C结构指针大小行为,c,pointers,64-bit,C,Pointers,64 Bit,我的代码中出现了一些奇怪的行为,这似乎是由于使用了泛型指针造成的,但实际上我完全不确定。我有一个相当标准的结构,如下所示: typedef struct { char* name; PyAutoCFunc ac_func; void (*func)(); PyAutoType type_id; int num_args; PyAutoType arg_types[MAX_ARG_NUM]; } func_entry; static func_entry* func_en
typedef struct {
char* name;
PyAutoCFunc ac_func;
void (*func)();
PyAutoType type_id;
int num_args;
PyAutoType arg_types[MAX_ARG_NUM];
} func_entry;
static func_entry* func_entries;
我正在存储一个静态指针,指向在堆上分配的这些结构元素的数组。在我创建这个数组的新元素并插入它时,它的值如下所示
func_entry new_fe;
new_fe.name = malloc(strlen(name) + 1);
strcpy(new_fe.name, name);
... // Init rest of struct
func_entries[num_func_entries] = new_fe;
num_func_entries++;
func_entry* fe = &func_entries[num_func_entries-1];
printf("Setting function '%s' at address '%p', name address '%p'\n", name, fe, fe->name);
这是一种输出
>>> Setting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0xe40fe0'
请注意fe->name的大小和值。然后将该指针存储到哈希表中,以便以后检索。在哈希表中,它存储为一个简单的void*。后来,当我从哈希表中检索指针时,发生了一件奇怪的事情
func_entry* fe = PyAutoHashtable_Get(func_table, c_func_name);
printf("Getting function '%s' at address '%p', name address '%p'\n", c_func_name, fe, fe->name);
它的输出
>>> Getting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0x6e6f74656c656b73'
fe的地址已经清楚地在哈希表中输入和输出,没有问题,但是fe->name的大小和地址已经更改。更奇怪的是,fe->name的大小与之前不同,甚至与fe的大小也不同。尝试访问fe->name会给我一个segfault,我不确定如何继续
出于兴趣,当我在具有多个链接库的应用程序中使用代码时,似乎会发生这种情况,我相当确定我运行的所有代码都是64位的
我已经在一个单独的应用程序中成功地运行了上述代码,并为fe->name(一个较小的)获得了一个正确的指针
我也在Ubuntu Linux 64位上运行,并使用gcc进行编译
这确实是我的C无知闪耀的地方,尽管我想象这可能是一百万件事情。任何人都可以发光吗?指针的大小总是相同的,无论是指向结构的指针还是通用指针(在过去是char*,在ANSI标准中是void*) 这里有一个简单的例子,我用它来解释结构和指针(虽然不是很详细,但你已经明白了)
希望有帮助。名称的地址看起来像是内存损坏的结果。它是完全未对齐的,这对于strdup从堆中返回的地址来说是不可能的
看起来您已超出所创建结构的范围。您提到它是在堆上创建的,但在代码中,它看起来可能是在堆栈上创建的。这不是在同一个函数中完成的,是吗?第一个块中的代码是否是在运行后一个块中的代码之前存在的函数?一旦退出该函数,该结构的内存就停止了,即使您保留了指向它的指针。后来,当您从哈希表中取出指针时,内存已被覆盖,不再有指向该表名称的指针。如果要传递指向结构的指针,请使用malloc动态分配它们。它们一直存在,直到您使用free显式地除去它们,而不是在函数结束时。看起来似乎有什么东西正在写入该数据结构。您看到的指针值
0x6e6f74656c656b73
看起来确实非常可疑-它是“noteleks”
的ASCII,即向后的“骨架”
。也许这可以让您了解是什么在覆盖您的数据。您可能需要显示分配fe->name的代码。如图所示,它似乎未初始化。地址似乎已更改-0xfe2d40!=0x20049e0。我同意Mark Wilkins的观点-我们需要看到更多的代码(尤其是PyAutoHastable_Get,但是设置名称的代码也是可疑的)。我真的不想发布我的整个hashtable实现,因为它实际上是一堆代码(尽管我已经使用它很长时间了,没有任何问题)。它为fe返回相同的值这一事实使我不那么怀疑它。正如@Harper所说的,0xfe2d40!=0x20049e0。您没有得到相同的结构指针,因此->name不一样也就不足为奇了。0xfe2d40很可能不在func_条目数组的末尾。0x6e6f74656c656b73看起来像字符串的一部分。如果将十六进制值6e 6f 74等解释为ASCII字符,则会得到“notelek”。颠倒顺序,你会得到“骷髅”。因此,func_entries数组可能损坏。指针不必都具有相同的大小。他们倾向于在现代桌面操作系统上安装指针,但对于异国情调的硬件,有一些例子表明一些指针有不同的大小。谢谢你的回答,但这对我的问题没有多大帮助。我对这些基本的东西相当熟悉。事实上,我认为指针有时可能有不同的大小。首先是32位对64位,其次在一些系统中函数指针的大小可能会有所不同:为了澄清我的说法,同一台机器上的指针大小都是相同的。只有在旧的DOS操作系统中,才有近指针和远指针,它们是不同的,但这是非标准的。丹尼尔,编译时有没有收到任何警告?PyAutoHashtable\u Get
是否返回func\u条目*
?否则,您需要将其强制转换为func\u条目*
。然后您可以使用fe_入口本身对结构进行操作。谢谢。骨架当然是经常出现在我的代码库中的字符串。听起来我可能在某个地方有更深层次的记忆衰退。谢谢!我有一种感觉,这并不完全是堆栈问题,但我使用的是realloc,内存的移动使散列中存储的指针无效!丹尼尔,你能澄清一下新职能的范围吗;?如果这是func中的一个局部变量,那么它绝对是指向一个局部释放堆栈变量的全局数组。您需要使用malloc或new调用在堆上分配func_项。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
int age;
};
void print(void *);
int main()
{
struct person *david;
if ((david = (struct person *)malloc(sizeof(struct person))) != NULL) {
david->name = strdup("David");
david->age = 40;
printf("sizeof david = %d, sizeof person = %d\n", sizeof david,
sizeof(struct person));
print((void *)david);
}
}
void print(void *p)
{
struct person *pp = (struct person *)p;
printf("sizeof p = %d, sizeof pp = %d\n%s %d\n", sizeof p, sizeof pp,
pp->name, pp->age);
}
sizeof david = 8, sizeof person = 16
sizeof p = 8, sizeof pp = 8
David 40