Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 预期时未收到seg故障_C_Arrays_Pointers_Struct_Segmentation Fault - Fatal编程技术网

C 预期时未收到seg故障

C 预期时未收到seg故障,c,arrays,pointers,struct,segmentation-fault,C,Arrays,Pointers,Struct,Segmentation Fault,我正在学习如何使用C语言中的指针和结构。当然,我试图故意破坏我的代码,以进一步了解该语言是如何工作的。下面是一些测试代码,它们按照我的预期工作: #include <stdio.h> #include <stdlib.h> struct pair { int x; int y; }; typedef struct pair pair; void p_struct( pair ); //prototype int main( int argc, ch

我正在学习如何使用C语言中的指针和结构。当然,我试图故意破坏我的代码,以进一步了解该语言是如何工作的。下面是一些测试代码,它们按照我的预期工作:

#include <stdio.h>
#include <stdlib.h>

struct pair {
    int x;
    int y;
};

typedef struct pair pair;

void p_struct( pair ); //prototype

int main( int argc, char** argv ) {
    pair *s_pair;
    int size, i;

    printf( "Enter the number of pair to make: " );
    scanf( "%d", &size );
    getchar();
    printf( "\n" );

    s_pair = (pair*)malloc( size * sizeof(pair) );

    for( i = 0; i < size; i++ ) {
        s_pair[i].x = i;
        s_pair[i].y = i;
        p_struct( s_pair[i] );
    }

    getchar();

    return (EXIT_SUCCESS);
}

void p_struct( pair s_pair ) {
    printf( "\n%d %d\n", s_pair.x, s_pair.y );
}
如前所述,就我所知,这段代码是功能性的

然后我决定修改代码的一部分,如下所示:

for( i = 0; i < size + 3; i++ ) {
    s_pair[i].x = i;
    s_pair[i].y = i;
    p_struct( s_pair[i] );
}
这种修改并没有产生我预期的seg故障错误。尽管我使用scanf函数为变量大小赋值时超出了显式设置的缓冲区,但所有对都被打印出来

据我所知,如果我错了,指针会纠正我的错误,当我为类型为pair s_pair的指针调用malloc函数时,堆中的内存管理器会保留一个大小为size*sizeofpair的连续内存块。我所做的是,当我将for循环修改为条件I 如果我理解正确的话,我的指针是否超出了它的保留内存限制,并且恰好处于清除状态,因为它右边的任何相邻部分都没有被其他数据占用?当缓冲区溢出时,这是正常行为吗

另外,当我使用I 作为记录,我还使用常规指针数组测试了这种行为:

int size, i, *ptr;

scanf( "%d", &size );

ptr = (int*)malloc( size * sizeof(int) );

for( i = 0; i < size + 15; i++ )
    ptr[i] = i;
这将产生与上述完全相同的结果。在i<尺寸+3时,seg故障似乎没有任何问题

最后,我还测试了一个阵列:

int i, array[10];

for( i = 0; i < 25; i++ )
    array[i] = i;
对于条件i<25,我会毫无疑问地得到seg故障。当我将其更改为I<15时,我没有收到seg故障

如果我没记错的话,指针数组和数组之间的唯一区别是分配给数组的内存位于堆栈上,而不是堆上。对此我不确定。记住这一点,并且考虑到阵列[10]不产生任何seg故障时i<15,为什么i<25会成为一个问题?在for循环期间,数组不是在堆栈的顶部吗?为什么它会关心额外的100个字节而不关心额外的60个字节?为什么数组缓冲区的上限不一直到为整个堆栈保留的任意内存块的末尾

希望所有这些对决定读一个稍微醉了的男人的闲话的人都有意义

如果我理解正确的话,我的指针是否超出了它的保留内存限制,并且恰好处于清除状态,因为它右边的任何相邻部分都没有被其他数据占用

差不多。除了你不清楚,因为相邻的东西可能被其他数据占用,你的代码只是在内存上踩了一下,改变了值。你可能永远不会注意到问题,或者你可能会在很久以后注意到问题。不管怎样,这都是未定义的行为

如果我理解正确的话,我的指针是否超出了它的保留内存限制,并且恰好处于清除状态,因为它右边的任何相邻部分都没有被其他数据占用


差不多。除了你不清楚,因为相邻的东西可能被其他数据占用,你的代码只是在内存上踩了一下,改变了值。你可能永远不会注意到问题,或者你可能会在很久以后注意到问题。不管怎样,这都是未定义的行为。

欢迎来到光荣的C世界

内存分配函数malloc、calloc、realloc等为您提供堆上的内存。当您调用其中一个,而您的程序没有足够的空间时,它会使您的程序无法获得更多空间。它不会以精确的增量完成这项工作,尽管它通常会以一定数量的整页增量完成这项工作。当索引超过数组末尾或甚至在数组开头之前时,仍在程序合法地址空间的范围内。只有当你离开你的程序所拥有的部分时,你才能得到一份工作


我强烈建议您使用来检查您的程序,特别是如果您有意尝试通过破坏东西来了解内存。除此之外,它还将在分配的两侧存储金丝雀值,以帮助您确定何时访问越界,并警告您双重释放和内存泄漏。

欢迎来到光荣的C世界

内存分配函数malloc、calloc、realloc等为您提供堆上的内存 . 当您调用其中一个,而您的程序没有足够的空间时,它会使您的程序无法获得更多空间。它不会以精确的增量完成这项工作,尽管它通常会以一定数量的整页增量完成这项工作。当索引超过数组末尾或甚至在数组开头之前时,仍在程序合法地址空间的范围内。只有当你离开你的程序所拥有的部分时,你才能得到一份工作


我强烈建议您使用来检查您的程序,特别是如果您有意尝试通过破坏东西来了解内存。除此之外,它还将在分配的任一侧存储金丝雀值,以帮助您确定何时访问越界,并警告您双重释放和内存泄漏。

当您调用malloc时,您可能会得到比所需更多的内存,因为内存是以公共块大小的倍数分配的。如果块大小是64字节,而您只要求10字节,那么操作系统将给您64字节,因此您仍然可以访问超出您请求范围的内存,这是您的程序正在观察的行为。

当您调用malloc时,您可能会得到比您需要的更多的内存,因为内存是按公共块大小的倍数分配的。如果块大小为64字节,而您只请求10字节,那么操作系统将给您64字节,因此您仍然可以访问超出您请求范围的内存,这是您的程序正在观察的行为。

正如其他人所说,未定义的行为并不意味着您的程序在所有情况下都会崩溃

这完全取决于覆盖数据的位置

可能什么都没有,因为C库没有在那里分配程序, 您可能已经覆盖了重要的管理信息,这些信息将在以后使用,然后才导致崩溃, 或者别的什么。
为了帮助您了解引擎盖下到底发生了什么,请打印地址,例如printf%p\n,s\u pair;或者类似的东西可能会有帮助,以及将程序编译成可读的汇编助记符,如gcc-S filename.c-o-

正如其他人所说,未定义的行为并不意味着程序在所有情况下都会崩溃

这完全取决于覆盖数据的位置

可能什么都没有,因为C库没有在那里分配程序, 您可能已经覆盖了重要的管理信息,这些信息将在以后使用,然后才导致崩溃, 或者别的什么。
为了帮助您了解引擎盖下到底发生了什么,请打印地址,例如printf%p\n,s\u pair;或者类似的方法可能会有所帮助,还可以将程序编译成可读的汇编程序助记符,如gcc-S filename.c-o-

未定义行为:当您执行未定义的操作时,您的代码不需要崩溃或出错。在某些平台上,当你做了一些非常错误的事情时,应用程序就会崩溃,这是很偶然的。不过,系统不需要捕捉到你在做未定义的事情;这是C..Undefined Behavior中隐藏bug的最常见来源:当您执行未定义的操作时,您的代码不需要崩溃或segfault。在某些平台上,当你做了一些非常错误的事情时,应用程序就会崩溃,这是很偶然的。不过,系统不需要捕捉到你在做未定义的事情;这是C中隐藏错误的最常见来源。虽然这可能是一个原因,但在本例中可能不是:malloc可能以8/16字节的倍数双/SSE对齐分配。提示:在程序结束时释放_对。虽然这可能是一个原因,但在本例中可能不是:malloc可能以8/16字节的倍数double/SSE aligned分配。提示:在程序结束时释放_对。