不久前,我在我写的某个大数字图书馆里发现了一个bug,花了我不少时间。问题是,我违反了某个结构成员的内存限制,但它没有segmentation fault或只是一个普通的崩溃,而是做了一些意外的事情(至少我没有预料到)。让我举个例子:
分段断层c

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

#define N 100 /* arbitrary large number */

typedef unsigned char byte;

void exitError(char *);
void segmentationFaultSignalHandler(int);

sig_atomic_t segmentationFaultFlag = 0;


int main(void)
{
    int i, memorySize = 0;
    byte *memory;
    if (setvbuf(stdout, NULL, _IONBF, 0))
        exitError("setvbuf() failed");
    if (signal(SIGSEGV, segmentationFaultSignalHandler) == SIG_ERR)
        exitError("signal() failed");
    for (i = 0; i < N; ++i)
    {
        printf("Before malloc()\n");
        if ((memory = malloc(++memorySize * sizeof(byte))) == NULL)
            exitError("allocation failed");
        printf("After malloc()\n");
        printf("Before segmentation fault\n");
        memory[memorySize] = 0x0D; /* segmentation fault */
        if (segmentationFaultFlag)
            exitError("detected segmentation fault");
        printf("After segmentation fault\n");
        printf("Before free()\n");
        free(memory);
        printf("After free()\n");
    }
    return 0;
}


void segmentationFaultSignalHandler(int signal)
{
    segmentationFaultFlag = 1;
}


void exitError(char *errorMessage)
{
    printf("ERROR: %s, errno=%d.\n", errorMessage, errno);
    exit(1);
}

正如我们所看到的,行memory[memorySize] = 0x0D;显然违反了malloc()给出的内存界限,但它不会崩溃或发出信号(我知道根据iso c99/iso c11,信号处理是实现定义的,当违反内存界限时根本不必发出信号)。它继续打印行After segmentation faultBefore free()After free(),但经过几次迭代之后,它崩溃了,总是在free()(打印After segmentation faultBefore free(),但不是After free())。我想知道是什么导致了这种行为,以及检测内存访问冲突的最佳方法是什么(我很惭愧,但我总是用printf来确定程序崩溃的位置,但肯定有更好的工具可以做到这一点),因为很难检测到(大多数情况下,它不会在违反代码时崩溃,但是,就像在示例中一样,在代码,当再次尝试使用此内存时)。当然,我应该能够释放这个内存,因为我分配正确,没有修改指针。

最佳答案

当你在记忆中读或写的时候,你没有自己的记忆,你会有不确定的行为。
这并不总是导致分割错误。实际上,代码很可能会损坏其他一些数据,并且程序会在其他地方崩溃,这使得调试变得很困难。
在本例中,您写入的堆地址无效。很可能您会损坏一些内部堆结构,这使得程序很可能在随后的malloc或free调用上崩溃。
有一些工具可以检查堆的使用情况,并告诉您是否超出了界限。我喜欢并推荐valgrind for linux和gflags for windows。

10-04 12:30
查看更多