Linux和Windows初始化结构不同

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux和Windows初始化结构不同相关的知识,希望对你有一定的参考价值。

从linux切换回windows时,我注意到我的代码停止了工作。使用可靠的调试器,我发现结构体的初始化方式不同。

typedef struct base{
    struct item * first;
}BASE;

typedef BASE *SPACE;

...

hashmap = malloc(sizeof(SPACE *) * length);
hashSpaceSize = length;

以这个代码为例(隐藏额外代码以保持整洁,同时忽略结构项,它在这里没用)。假设长度为3.在Linux中,当我检查调试器时,我看到:

hashmap[0] = NULL;
hashmap[1] = NULL;
hashmap[2] = NULL;

因为我没有初始化BASE,所以我只是初步确定了它们的数组。但是,在Windows中,我看到所有BASES都已初始化。不仅如此,BASE中的所有ITEM也都已初始化。

但是,如果我,例如,之后立即添加这一行:hashmap[0]->first = NULL,我最终得到一个SIGSEGV错误,我无法找到原因。在Linux中,这是因为hashmap[0] is NULL,因此hashmap[0]->first甚至无法首先访问。但是在Windows上,它清楚地表明hashmap [0]存在并具有初始化的first值。

我不知道这里发生了什么,我找不到任何关于这个bug的信息。如果需要更多的代码,一切都在我的github.链接到这个代码所在的实际文件。但是现在,我对发生了什么感到困惑...

更新:显然我有一些想要做的事情。不知道malloc返回了一个未初始化的指针,而不仅仅是NULL。那是由Linux设定的。谢谢,今天学到了新东西。

答案

在成功调用malloc之后指向的字节值未初始化。这意味着它们可以设置为任意值,包括零。所以只是因为字节为零或非零并不意味着它们被初始化。

关于C standard州的malloc第7.22.3.4节:

1

#include <stdlib.h>
void *malloc(size_t size);

2 malloc函数为一个对象分配空间,该对象的大小由size指定,其值是不确定的。

因此无法保证malloc返回的内存将包含什么。

另一方面,如果使用calloc,该函数会将所有分配的字节初始化为0。

hashmap = calloc(length, sizeof(SPACE *));
另一答案

假设长度为3.在Linux中,当我检查调试器时,我看到:

hashmap[0] = NULL;
hashmap[1] = NULL;
hashmap[2] = NULL;

因为我没有初始化BASE,所以我只是初步确定了它们的数组。

不,你得到的所有这些都是NULL,因为这恰好是你得到的。 C没有指定malloc()返回的内存的初始内容,如果在其他情况下执行了该分配,那么您可能无法获得所有NULL。

但是,在Windows中,我看到所有BASES都已初始化。不仅如此,BASE中的所有ITEM也都已初始化。

它们可能具有非NULL值,但这与初始化非常不同。这些值很可能是狂野的指针。如果它们恰好指向可访问的内存,那么您可以将它们指向的数据解释为ITEMs,但同样,这并不意味着它们已初始化,或者访问该内存是安全的。您正在深入研究未定义的行为。

但是,如果我,例如,之后立即添加此行:hashmap [0] - > first = NULL,我最终得到一个SIGSEGV错误,我无法找到原因。

我们无法说出您的分段错误的原因,因为您没有提供负责的代码,但拥有一个指针数组并不意味着其中的指针值是有效的。如果不是,则取消引用它们会产生未定义的行为,这通常表现为段错误。请注意,这不依赖于那些指针是NULL;它可以访问任何指向未指向属于您的程序的对象并具有兼容类型的指针值。

在Linux中,这是因为hashmap [0]为NULL,因此首先甚至无法访问hashmap [0] - >。但在Windows上,它清楚地表明hashmap [0]存在并具有初始化的第一个值。

不,它没有。同样,你的调试器显示hashmap[0]具有非NULL值,这根本不是同一个东西。

您有责任避免取消引用无效指针值,这些值绝不仅限于NULL

以上是关于Linux和Windows初始化结构不同的主要内容,如果未能解决你的问题,请参考以下文章

linux 第三周

LINUX PID 1和SYSTEMD PID 0 是内核的一部分,主要用于内进换页,内核初始化的最后一步就是启动 init 进程。这个进程是系统的第一个进程,PID 为 1,又叫超级进程(代码片段

ImGui 示例代码/基本初始化不起作用(Windows 和 Linux)

终于懂了:Delphi重定义消息结构随心所欲,只需要前4个字节是消息编号就行了,跟Windows消息虽然尽量保持一致,但其实相互没有特别大的关系。有了这个,就有了主动,带不带句柄完全看需要。(代码片段

linux下的程序如何在windows下运行

详细解析Linux目录结构