不久前,我在我编写的某个大型数字库中寻找错误,这让我花了很多时间。问题是我违反了某些结构成员的内存边界,但不是 段错误
或只是普通的崩溃,它做了一些意想不到的事情(至少我没想到)。让我举个例子:
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 fault
、Before free()
和 After free()
行,但经过几次迭代后它崩溃了, 始终在 free()
(打印 After segmentation fault
和 Before free()
,但不打印 After free()
).我想知道是什么导致了这种行为,以及检测内存访问违规的最佳方法是什么(我很惭愧,但我总是有点用 printf
来确定程序崩溃的位置,但肯定有更好的工具来做到这一点)因为它很难检测(通常它不会在违规代码处崩溃,但是,如示例所示,在代码的后面,当再次尝试使用此内存执行某些操作时)。当然,我应该能够释放这 block 内存,因为我正确地分配了它并且没有修改指针。
最佳答案
您只能在伪造的环境中检测违规行为。 在这种情况下,您违反了从系统中获得的内存,您将无法再相信任何事情。因为现在发生的所有事情都是未定义的行为,你不能期望会发生什么,因为没有任何规则。
因此,如果您想检查程序是否存在内存泄漏或某些读/写违规。您必须编写一个程序来获取属于它的内存区域,并将该区域的一部分提供给“待检查”程序。您必须检查进程并跟踪它写入和读入我们内存的位置,并且您必须使用内存的另一部分来检查是否允许在那里读写(即在您的伪造环境中通过设置一些 FLAGS 并检查它们是否已更改)。
因为如果程序离开你拥有的区域。你不能确定你是否会检测到这种行为。 所以你必须自己做内存管理来检查这种行为。
关于c - 内存分配违规后 free() 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21330233/