malloc()-C中的奇怪分段错误

malloc()-C中的奇怪分段错误,c,linux,segmentation-fault,malloc,C,Linux,Segmentation Fault,Malloc,您好,我正在编写一个程序,我用以下方式声明了一个字符串: char *string=malloc(sizeof(char)); 在我的笔记本电脑中,我使用的是64位Mint操作系统,一切正常。但是在32位Debian机器中,我在那一行代码中遇到了一个分段错误。如果我声明的字符串没有malloc,比如:char string[100]该程序运行正常。当我使用GDB运行该程序时,它会显示malloc.c未找到或类似的内容。这种行为合乎逻辑吗?如果有人以前遇到过同样的问题,请向我解释为什么会发生这种

您好,我正在编写一个程序,我用以下方式声明了一个字符串:

char *string=malloc(sizeof(char));

在我的笔记本电脑中,我使用的是64位Mint操作系统,一切正常。但是在32位Debian机器中,我在那一行代码中遇到了一个分段错误。如果我声明的字符串没有malloc,比如:char string[100]该程序运行正常。当我使用GDB运行该程序时,它会显示malloc.c未找到或类似的内容。这种行为合乎逻辑吗?如果有人以前遇到过同样的问题,请向我解释为什么会发生这种情况?提前谢谢。

您只为字符串分配了1个字节,因此,您可能过度编写了其他变量或malloc堆结构

更改:

char *string=malloc(sizeof(char));
更真实的尺寸,例如:

char *string=malloc(256);

您只为字符串分配了1个字节,因此可能过度编写了其他变量或malloc堆结构

更改:

char *string=malloc(sizeof(char));
更真实的尺寸,例如:

char *string=malloc(256);

再加上另一个答案,我试图解释为什么它在32位上失败,但在64位上成功:

最可能的情况是,内存管理器的工作粒度取决于系统的字大小。在32位系统上可能是4字节,在64位系统上可能是8字节。(不过,我不确定这是否正确。)

如果分配1个字节,则有3个字节。7个未使用的字节。所以,虽然你不被允许使用它们,但什么也不会发生


如果使用超过3个字节,但最多7个字节,则在64位系统上不会发生任何事情,但在32位系统上,程序会崩溃。

在另一个答案中,我尝试解释为什么它在32位上失败,但在64位上成功:

最可能的情况是,内存管理器的工作粒度取决于系统的字大小。在32位系统上可能是4字节,在64位系统上可能是8字节。(不过,我不确定这是否正确。)

如果分配1个字节,则有3个字节。7个未使用的字节。所以,虽然你不被允许使用它们,但什么也不会发生


如果使用超过3个字节,但最多7个字节,则64位系统上不会发生任何事情,但在32位系统上,程序会崩溃。

要分配100个字符的字符串,必须分配101个字符,+1是结尾字符
'\0'
,因此:

char *string = malloc(sizeof(char) * 101);
sizeof(char)
允许创建与您的操作系统兼容的char(65/32位)

在64位系统或32位系统中,字符的大小总是相同的,但是对于其他类型,如
int
long
,它们在32位或64位上的大小不同

要分配100个字符的字符串,您必须分配101个字符,+1是结尾字符
'\0'
,因此:

char *string = malloc(sizeof(char) * 101);
sizeof(char)
允许创建与您的操作系统兼容的char(65/32位)

在64位系统或32位系统中,字符的大小总是相同的,但是对于其他类型,如
int
long
,它们在32位或64位上的大小不同

来自malloc上的POSIX:

The pointer returned if the allocation succeeds shall be suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object in the space allocated (until the space is explicitly freed or reallocated). 
这是未定义的行为,但解释在于短语“适当对齐”。 这是完全由实现定义的,但对于大多数体系结构来说,它必须至少在字边界上

假设这是真的,那么一个字的大小可以指示下一个可能的“适当对齐”内存位置的位置:距离分配的1字节缓冲区的开始4字节或8字节

因此,除了这段代码有问题外,解释似乎是实现允许写入超出malloc末尾的某些字节,其中“某些字节”是字号的函数。

来自malloc上的POSIX:

The pointer returned if the allocation succeeds shall be suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object in the space allocated (until the space is explicitly freed or reallocated). 
这是未定义的行为,但解释在于短语“适当对齐”。 这是完全由实现定义的,但对于大多数体系结构来说,它必须至少在字边界上

假设这是真的,那么一个字的大小可以指示下一个可能的“适当对齐”内存位置的位置:距离分配的1字节缓冲区的开始4字节或8字节


因此,除了这段代码有问题外,解释似乎是,实现允许写入超出malloc结尾的一些字节,其中“某些字节”是字号的函数。

好的,谢谢你的回答。我声明为char*str;但是它给了我一个未初始化的警告,这就是为什么我使用malloc。我理解我的错误。但是为什么尽管它有那个错误,它在64位而不是32位时工作正常?仅仅因为某些东西在一个环境中工作并不意味着代码是正确的-你只是在一个环境中幸运,而不是在另一个环境中-仅此而已。好的,谢谢你的回答。我声明它为char*str;但是它给了我一个未初始化的警告,这就是为什么我使用malloc。我理解我的错误。但是为什么尽管它有那个错误,它在64位而不是32位时工作正常?仅仅因为某些东西在一个环境中工作并不意味着代码是正确的-你只是在一个环境中幸运而不是在另一个环境中-仅此而已。仅供参考,找不到
malloc.c
是正常的,除非您已经为它安装了源代码并将其添加到GDB的源代码路径中。没有什么理由这样做。它仍然可以工作,因为编译器将其链接到二进制文件,而不是源文件。仅供参考,未找到
malloc.c
是正常的,除非您为其安装了源文件并将其添加到GDB的源文件路径。没有什么理由这样做。它仍然有效,因为编译器将其链接到二进制文件,而不是源代码。好的,我理解。非常感谢您的解释!)我不明白这怎么是最好的答案。我可以总结为:这是UBP@netcoder我自己也是这样认为的,但这是对问题“为什么它在64位上工作,而不是在32位上工作?”部分的回答。它说明了UB不可靠的原因,因为它有时有效,有时无效