热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一个C语言的惨痛教训

一个c语言动态库开发的惨痛教训,作为警示,希望大家不要碰到这类问题。背景交代下背景,最近的一个项目,apachemodule开发,使用的是c语言。这个其实比较无奈,apachemod_dav.h中

一个c语言动态库开发的惨痛教训,作为警示,希望大家不要碰到这类问题。

背景

交代下背景,最近的一个项目,apache module开发,使用的是c语言。这个其实比较无奈,apache mod_dav.h中声明的dav_error结构体,其中一个字段就是const char *namespace,这不是鄙视C++吗?

虽然有方法可以绕过,搞成C++的,最后还是决定用c语言开发。

悲剧

悲剧就是这样发生的。

调试发现模块crash频繁,用gdb调试,结果让人迷惑,在pool上分配的地址竟然out of bound,诸如如下面的代码。

ptr = apr_psprintf(r->pool, "%s", ns, ptr, ns);

resp = apr_pcalloc(pool, sizeof(*resp));

resp->href = apr_pstrdup(pool, uri);

...

而且有时候程序crash时,发现函数的入栈参数明显有问题,参数错位。折腾了两天也没查出是什么原因。怀疑是pool被程序破坏了,但该pool上分配的其他地址都很正常,检查n+1编程序也没发现什么问题。搞的相当于郁闷。本来感到apr的内存分配系统还是挺不错的,不过现在想想,pool要是真的不小心被程序破坏了,那也是相当难以查出来的。

发现原因

按照pool破坏的思路折腾了几天,实在是没找到头绪。这个问题原因的发现还是听偶然的,就是仔细检查编译警告时,发现编译器对于apr_xxx的string系列操作函数发出警告:

 warning: assignment makes pointer from integer without a cast

我算是比较粗心的,对编译错误一般不仔细看,发现这个警告要归功于我的一位可爱的同事微笑

当时我看到这个警告就怀疑,是不是这个原因引起的crash。阴霍的天空无疑透出了一丝光亮。

相关.h文件没有包含导致编译器不认识这些库函数,如同编译warning所显示的那样:于是c语言就会把指针cast为int。由于编译机器是64位linux,如果把分配的地址空间cast到32位的int型数据,那么对于超过4G的地址空间来讲,这个结果就是一场灾难。

通常情况,如果函数没有定义,本来在运行时会报链接错误。但是这些是库函数,所以能够正常链接。

添加头文件,重新编译运行。程序不再crash。

十年被蛇咬。马上动手把所有的编译warning都修复掉。怕了...

教训

不要忽略编译warning

编译条件要严,像函数没有声明这种情况,应该设置为error,而非warning。我们的编译框架不够严格。


推荐阅读
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 本文主要介绍了gym102222KVertex Covers(高维前缀和,meet in the middle)相关的知识,包括题意、思路和解题代码。题目给定一张n点m边的图,点带点权,定义点覆盖的权值为点权之积,要求所有点覆盖的权值之和膜qn小于等于36。文章详细介绍了解题思路,通过将图分成两个点数接近的点集L和R,并分别枚举子集S和T,判断S和T能否覆盖所有内部的边。文章还提到了使用位运算加速判断覆盖和推导T'的方法。最后给出了解题的代码。 ... [详细]
  • 1Lock与ReadWriteLock1.1LockpublicinterfaceLock{voidlock();voidlockInterruptibl ... [详细]
  • ProblemDescriptionXiaoAlivesinavillage.Lastyearfloodrainedthevillage ... [详细]
author-avatar
youyiyang
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有