C语言由于未包含头文件引起的段错误的两个例子

1. 未包含头文件引起函数返回值错误

出错代码:

myPointer = umalloc(xxx);
if (myPointer)
{
    myPointer->memberA = aaaa;
	....
}

在64位机器上,运行上面代码, 在执行到第4行的时候会出现段错误。

原因:

在上述代码中, umalloc 是在另一个文件uMem.c 里面定义的, 如下。文件声明在uMem,h中。但是上面的代码并未包含此头文件,在编译时,由于没有包含头文件,umalloc函数被默认为返回类型是int,并产生一个waringing,提示第一行代码有一个警告,将interger强制转换为了Pointer。

void *uMalloc(uint32_t num_bytes)
{
    void *value;
    
    value = malloc(num_bytes);
    if (value == NULL)
    {
        return NULL;
    }

    memset(value, 0, num_bytes);
    return value;
}

执行时, 在gdb中调试发现umalloc函数里分配的指针值为 0x7fffe800eb40,但是函数返回时被强制转换为了32位的int值0xe800eb40,再赋值给myPointer的时候,再次被转换为64位指针,由32位填充为64位,但这个时候的值变为了0xffffffffe800eb40。在第4行向这个地方赋值时,导致系统崩溃。

此问题在32位系统上运行是没有问题的。

2. 函数参数传递错误

在模块内部定义函数的原型声明为 xxxModuleInit(int maxSize); 在模块外部,在调用的时候,没有传参数进来,直接调用的xxxModuleInit();

由于没有包含头文件,编译器默认该函数参数为void,所以编译到这里,连一个warning都没有,导致到了执行阶段才报错,而且有一定的随机性,有些时候带的垃圾数据刚好执行没问题,但是在下次执行其它地方的代码时才异常,有一定的干扰。

通常C语言并不要求函数一定要在被调用之前定义,编译器在处理到某个未知类型的函数时,会为其创建一个隐式声明,并假设该函数返回值类型为int。但编译器无法检查传递给该函数的实参类型和个数是否正确,所以这不利于编译器为我们排除错误。

猜你喜欢

转载自blog.csdn.net/Candy1232009/article/details/80723054