網站首頁 編程語言 正文
??今天遇到了因為include順序不同而編譯結果不同的問題。歸根結底還是自己寫代碼的習慣不好導致的。
編譯環境
??既然要寫就多寫點吧。最近又開始做TI的DSP C6455相關的開發了。之前的文章里有寫到,TI提供有一個CSL庫,但是比較老,輸出的格式是COFF,而現在一般是ELF。如果做一些新的開發的話,建議重新編譯CSL庫,并選擇輸出為ELF格式。
??C6000 DSP的編譯工具鏈目前主要有7.4和8.3版本。8.0以上的版本不再支持C6455了,所以我目前用的CGT版本是7.4.24,7.4版本的應該都差不多,因為文檔都是一樣的。
問題簡化
??實際工程中包含大大小小的文件很多,頭文件的include層層嵌套。所以我在這里為了說明關鍵問題,把我實際遇到的問題做了簡化。整個工程包含三個文件main.cpp, CData.cpp和CData.hpp。源碼如下:
// main.cpp
/* Scenario 1: it doesn't work */
#include "csl_types.h"
#include "CData.hpp"
/* Scenario 2: it does work */
// #include "CData.hpp"
// #include "csl_types.h"
int main(void) {
return 0;
}
// CData.cpp
#include "CData.hpp"
// CData.cpp
#ifndef CDATA_HPP_
#define CDATA_HPP_
#include <assert.h>
#include <stdlib.h>
class CData {
public:
CData(): m_pData(NULL), m_nCnt(0) {}
CData(int nCnt): m_nCnt(nCnt) {
m_pData = new int[nCnt];
assert(m_pData != NULL);
}
~CData(){
if(m_pData){
delete[] m_pData;
m_pData = NULL;
}
}
protected:
int *m_pData;
int m_nCnt;
};
#endif
??實際上的現象就是main.cpp中include了兩個頭文件,它們include的前后順序不同,導致了編譯結果不同。在第一種情況下編譯得到這樣的結果:
??而在第二種情況下就是能夠正常完成編譯。
問題分析
a value of type "void *" cannot be used to initialize an entity of type "int *"
a value of type "void *" cannot be assigned to an entity of type "int *"
??報錯提示的問題和NULL有關,大概意思是NULL是一個void *的類型,不能把它賦給其他類型的變量。但可以看到,單獨編譯CData.cpp是沒有出現問題的。而在編譯main.cpp的時候,因為先include了csl_types.h,導致改變了NULL的定義,所以出了問題。
??查找有NULL相關的定義的文件可以找到:
// stdlib.h
#ifndef NULL
#define NULL 0
#endif
// csl_types.h
#ifndef NULL
#define NULL ((void*)0)
#endif
// xdc/std.h
#undef NULL
#if defined(__cplusplus) || !defined(xdc__strict)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
??stdlib.h大家應該都比較熟悉,是標準庫。csl_types.h是在用CSL的時候會不經意間包含的一個頭文件。還有xdc/std.h是在用RTSC時可能會用到的頭文件。這幾個文件里都有關于NULL的定義。
??我這次遇到的問題就是因為前兩個文件include的前后順序不同,NULL定義的情況也就不同了。而第三個文件感覺比較好,會先undef NULL,然后再重新define,應該可以一定程度上避免這個問題。但是第三個文件中有些類型的定義也會和csl_types.h產生沖突,所以用起來還是要注意。
總結
??這次雖然兩個頭文件include的順序引發的問題。但是歸根結底我覺得還是因為我直接在頭文件里做類(CData)的定義,而沒有把定義放在cpp文件中。如果把方法的具體實現放在源文件里,然后把那些頭文件中的include放到源文件里去,應該可以一定程度上避免這種問題的出現。
??實際工程中遇到這類問題,往往include有多層,很難發現,所以還是應該要有一個良好的編程習慣!
原文鏈接:https://blog.csdn.net/qq_35787848/article/details/124331375
相關推薦
- 2023-07-26 webpack原理之開發第一個loader
- 2022-09-06 python?如何實現跳過異常繼續執行_python
- 2022-09-27 React?Native?中限制導入某些組件和模塊的方法_React
- 2022-11-24 C++?如何使用棧求解中綴、后綴表達式的值_C 語言
- 2022-11-05 GO?CountMinSketch計數器(布隆過濾器思想的近似計數器)_Golang
- 2022-06-01 python機器學習sklearn實現識別數字_python
- 2022-11-11 C++?左值引用與一級指針示例詳解_C 語言
- 2022-08-10 C#實現同步模式下的端口映射程序_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支