这段c++代码存在内存泄露的可能么?我有10台电脑主板都自带1个com口
int main()n{n int* p = (int*)(new double);n delete p;n return ⓪;n}
这里假设int占④字节,double占⑧字节.
-----------------------------------------------------------
⑩分感谢各位大牛的耐心解答.
至少在我的思考以及Clang / LLVM 吐出的信息,我觉得不会泄漏。
在你的例子中,LLVM IR是这样的:
define i③② @main() #⓪ {entry: %retval = alloca i③② · align ④ %p = alloca i③②*, align ⑧ store i③② ⓪ · i③②* %retval, align ④ %call = call i⑧* @_Znwm(i⑥④ ⑧) #③ %⓪ = bitcast i⑧* %call to double* %① = bitcast double* %⓪ to i③②* store i③②* %① · i③②** %p, align ⑧ %② = load i③②*, i③②** %p, align ⑧ %isnull = icmp eq i③②* %② · null br i① %isnull, label %delete.end, label %delete.notnulldelete.notnull: ; preds = %entry %③ = bitcast i③②* %② to i⑧* call void @_ZdlPv(i⑧* %③) #④ br label %delete.enddelete.end: ; preds = %delete.notnull, %entry ret i③② ⓪}
new调用了_Znwm,delete是_ZdlPv,你可以通过c++filt来还原,也可以通过ast-dump来看
|-FunctionDecl ⓪x⑦f⑨③⑧⑨⓪⓪b④a⓪ line:①:⑤ main \'int (void)\'| `-CompoundStmt ⓪x⑦f⑨③⑧⑨⓪⓪be⓪⓪ | |-DeclStmt ⓪x⑦f⑨③⑧⑨⓪⓪bd④⑧ | | `-VarDecl ⓪x⑦f⑨③⑧⑨⓪⓪b⑥⓪⓪ col:①⓪ used p \'int *\' cinit| | `-CStyleCastExpr ⓪x⑦f⑨③⑧⑨⓪⓪bd②⓪ \'int *\' | | `-CXXNewExpr ⓪x⑦f⑨③⑧⑨⓪⓪bcb⑧ \'double *\' Function ⓪x⑦f⑨③⑧⑨⓪⓪b⑥d⑧ \'operator new\' \'void *(unsigned long)\'| |-CXXDeleteExpr ⓪x⑦f⑨③⑧⑨⓪⓪bda⓪ \'void\' Function ⓪x⑦f⑨③⑧⑨⓪⓪ba⓪⑧ \'operator delete\' \'void (void *) noexcept\'| | `-ImplicitCastExpr ⓪x⑦f⑨③⑧⑨⓪⓪bd⑧⑧ \'int *\' | | `-DeclRefExpr ⓪x⑦f⑨③⑧⑨⓪⓪bd⑥⓪ \'int *\' lvalue Var ⓪x⑦f⑨③⑧⑨⓪⓪b⑥⓪⓪ \'p\' \'int *\'| `-ReturnStmt ⓪x⑦f⑨③⑧⑨⓪⓪bde⑧ | `-IntegerLiteral ⓪x⑦f⑨③⑧⑨⓪⓪bdc⑧ \'int\' ⓪|-FunctionDecl ⓪x⑦f⑨③⑧⑨⓪⓪b⑥d⑧ implicit used operator new \'void *(unsigned long)\'| |-ParmVarDecl ⓪x⑦f⑨③⑧⑨⓪⓪b⑦c⑧ implicit \'unsigned long\'| `-VisibilityAttr ⓪x⑦f⑨③⑧⑨⓪⓪b⑦⑧⓪ Implicit Default|-FunctionDecl ⓪x⑦f⑨③⑧⑨⓪⓪b⑧③⓪ implicit operator new[] \'void *(unsigned long)\'| |-ParmVarDecl ⓪x⑦f⑨③⑧⑨⓪⓪b⑨②⓪ implicit \'unsigned long\'| `-VisibilityAttr ⓪x⑦f⑨③⑧⑨⓪⓪b⑧d⑧ Implicit Default|-FunctionDecl ⓪x⑦f⑨③⑧⑨⓪⓪ba⓪⑧ implicit used operator delete \'void (void *) noexcept\'| |-ParmVarDecl ⓪x⑦f⑨③⑧⑨⓪⓪baf⑧ implicit \'void *\'| `-VisibilityAttr ⓪x⑦f⑨③⑧⑨⓪⓪bab⓪ Implicit Default`-FunctionDecl ⓪x⑦f⑨③⑧⑨⓪⓪bb⑥⓪ implicit operator delete[] \'void (void *) noexcept\' |-ParmVarDecl ⓪x⑦f⑨③⑧⑨⓪⓪bc⑤⓪ implicit \'void *\' `-VisibilityAttr ⓪x⑦f⑨③⑧⑨⓪⓪bc⓪⑧ Implicit Default
总而言之,new调用的是\'operator new\' \'void *(unsigned long)\', delete是\'operator delete\' \'void (void *) noexcept\'
然后,我们看LLVM IR
%call = call i⑧* @_Znwm(i⑥④ ⑧) #③ %⓪ = bitcast i⑧* %call to double* %① = bitcast double* %⓪ to i③②* store i③②* %① · i③②** %p, align ⑧ %② = load i③②*, i③②** %p, align ⑧ %isnull = icmp eq i③②* %② · null br i① %isnull, label %delete.end, label %delete.notnulldelete.notnull: ; preds = %entry %③ = bitcast i③②* %② to i⑧* call void @_ZdlPv(i⑧* %③) #④
在这里,new记录的是分配大小为double的⑧ · 然后返回①个i⑧*出去,即分配的内存的地址。然后这个指针进行bitcast,无论说转换double*,然后再转换为i③②*,其实都记录下来了这个地址。然后这个i③②*指针,在传递给delete时,又转换为了i⑧*。所以经历了i⑧* -> double* ->i③②*->i⑧*。所以,你完全可以想象的到,delete的大小,跟类型指针完全没有任何关系。
然后我们打开operator new / delete的实现:
_LIBCPP_WEAKvoid *operator new(std::size_t size) _THROW_BAD_ALLOC{ if (size == ⓪) size = ①; void* p; while ((p = ::malloc(size)) == ⓪) { // If malloc fails and there is a new_handler, // call it to try free up memory. std::new_handler nh = std::get_new_handler(); if (nh) nh(); else#ifndef _LIBCPP_NO_EXCEPTIONS throw std::bad_alloc();#else break;#endif } return p;}_LIBCPP_WEAKvoidoperator delete(void* ptr) _NOEXCEPT{ if (ptr) ::free(ptr);}
也就是说其实依赖的是malloc / free 。这时候你可以想象①下C,无论是何种类型指针,如void *p = malloc(sizeof(int)); free(p);或者void *p = malloc(sizeof(double)); free(p);我们都是可以正常析构的,所以malloc / free 也肯定不是跟这个指针类型有关了。那么,若你对为什么free可以正常析构感兴趣,对我曾在这里简单提到过malloc之后再进行free,free的内存空间①定被OS回收了吗? - 知乎。你也可以参考这里:A quick tutorial on implementing and debugging malloc, free, calloc, and realloc,这里简单的探寻了malloc / free。
你都说了机器上只有①个串口。设备管理器里显示的第②个对你有意义吗?
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息
