写了好几个月,收尾阶段了,本来以为可以结束了
结果遇到了问题 实在无法解决。代码还算有点大,接近1W5行的样子
问题出在了使用了泛型list,里面都是存储结构体
然后大量的在调用过程中使用,调用过程又都是在线程里面。
线程要多次 启动和结束,每次启动和结束的时候都会发现内存一下子上去了,然后在线程运行中会发现内存也是缓慢增加的。用了工具定位,全部都定位到泛型list创建的位置,查了一下资料。有可能有几种原因。也不确定。(delphi2010)
1、泛型list里面的结构体是有string类型的,释放不干净,这个也不知道怎么处理。
2、泛型list在过程里面调用了clear方法,没有释放对象(这个我做过实验,貌似内存没增长)
3、泛型list本身就有问题,是一个编译器bug,需要版本更新。
4、我代码本身的问题,有些地方没释放,但是我是窗体创建的时候创建,窗体销毁的时候free的,最后也没提示内存泄露啊。在中间过程的内存不断上涨(多线程 启动之后 内存先增加再减少,然后稳定,线程结束之后重新启动 内存一下子增加了好多。中间我都是用clear去清理的不知道是不是这个原因)
5、问了论坛的一些朋友 一般给的代码都是 创建没多久就销毁了,问题是我的程序需要创建 之后 在线程里面多次操作
线程也是多次的 启动 退出 最后程序完全退出的时候才退出。(这样的话 借用别人的话来说 就是要考虑生命周期的问题)可是我不会处理
经过这几个月的代码编写,我深深的感到了delphi  程序员的无奈 资料很难找 问了之后 即使有回答的 也是要自己重新摸索好久。有些底层的东西  要自己处理 处理不好 往往问题很大。
诶,好多天没好好休息了。有愿意聊的,说个话。
聊的开心的就当散分吧。多线程内存泛型

解决方案 »

  1.   

      估计是线程处理不好,导致内存溢出。
      java和C#,都有内存回收机制,delphi7和C++等没有。
      所以用delphi开发时,一定要注意对象的创建、释放。
      如果是循环处理,或链表里有对象,还要注意clear(清除内存中,变量的堆栈区,而非栈区。)  我是窗体创建的时候创建,窗体销毁的时候free的,
      最后也没提示内存泄露啊。在中间过程的内存不断上涨。
      ---对象变量是一个,但中间可以创建多个对象给变量,最后free,
         只是释放了最后一个创建的对象的堆栈区,其他先前几个未free,所以内存溢出了。  delphi是核心类库功能强,外围类功能弱,外围类种类有限。
      所以很多时候靠第三方类来弥补。  楼主觉得累,可以改为C#开发。
      

  2.   

    1、string类型是生存期自管理的,我觉得对于delphi这么一个多年的编译器不太可能在这方面出现问题,这应该是你排查完其他所有bug的最后一步。另外如果你信不过string,你完全可以用pchar代替string,自己分配自己释放。
    2、clear方法不会释放对象,只会清除entries,自己创建的对象必须自己释放。
    3、这个问题参照第一个回答,我觉得这不太可能是delphi的问题。你也可以去官方看看有没有这个bug的记录。
    4、调用free,只是保证对象在析构时,会析构它所包含的对象,但在堆中创建的对象必须要显示释放,析构不会自动去释放这些对象(在d7以前是这样,新版的应该这点是不会变的),例如TMyClass中你为一个指针p分配了内存,如果你在TMyClass的析构函数中没有显示释放p,那你调用TMyClass的free也不会释放p,就是说free只会保证调用析构函数,但你的析构函数是什么样的它不管。内存泄漏检测建议用e什么log的一个软件,很不错。
    5、可以考虑线程池
      

  3.   

    1、string类型是生存期自管理的,我觉得对于delphi这么一个多年的编译器不太可能在这方面出现问题,这应该是你排查完其他所有bug的最后一步。另外如果你信不过string,你完全可以用pchar代替string,自己分配自己释放。----这个没写过 而且是结构体 写起来很麻烦啊
    2、clear方法不会释放对象,只会清除entries,自己创建的对象必须自己释放。---主要是想清理内存 不让内存暴涨
    3、这个问题参照第一个回答,我觉得这不太可能是delphi的问题。你也可以去官方看看有没有这个bug的记录。----有一个朋友说有 ,我也不清楚,很少关注这个。
    4、调用free,只是保证对象在析构时,会析构它所包含的对象,但在堆中创建的对象必须要显示释放,析构不会自动去释放这些对象(在d7以前是这样,新版的应该这点是不会变的),例如TMyClass中你为一个指针p分配了内存,如果你在TMyClass的析构函数中没有显示释放p,那你调用TMyClass的free也不会释放p,就是说free只会保证调用析构函数,但你的析构函数是什么样的它不管。内存泄漏检测建议用e什么log的一个软件,很不错。----我就是用那软件检测出来的,只是不知道怎么修改  他定位的地址全部在创建的地方。
    5、可以考虑线程池------这样写法估计更复杂了 几个线程+临界 和协调 就已经很麻烦了
    可否告之联系方式 bluekitty 
      
      

  4.   

    没用过泛型,呵呵,一直用旧版的List,除了操作麻烦点感觉也没什么。一般写个类包装一下看起来就和泛型差不多了。
    总有种感觉:泛型方便的同时又不太安全。不知道我说的对不对?毕竟没接触过泛型的内存管理。
    听网上说泛型有不少BUG,我想还是等它成熟点再用。
    注意休息!
      

  5.   

    般写个类包装一下看起来就和泛型差不多了。----------这个怎么写?
    总有种感觉:泛型方便的同时又不太安全。不知道我说的对不对?毕竟没接触过泛型的内存管理。
    听网上说泛型有不少BUG,我想还是等它成熟点再用。
    具体怎么写?type
    Tso=packed record 
    jiu:Integer;
    zu:Integer; 
    mu:Integer;  
    sn:Tsn; 
    end;
    type
    Tsn=packed record 
    i:Integer; 
    ng:Integer; 
    sng:Integer; 
    mng:Integer; 
    je:Integer;
    wi:Integer; 
    di:Integer; 
    mi:string;  
    end;比如这样的结构体  我想能跟泛型的list一样 可以增加 删除 清理 排序之类的操作
      

  6.   

    泛型clear并不会释放其中的对象啊,如果做到谁分配谁保证释放,就没那么多内存泄露了
      

  7.   

    对于某个特定类型就写个对应的代理类,类中包含一个私有的TList:
    TSOList = class
    private
      FList: TList;
    public
      procedure Add(so: Tso);
      procedure Delete(i: integer);
      procedure Insert(i: integer;so: TSO);
      procedure Clear;  contructor Create;
      destructor Destroy; override;
    end;constructor TSOList.Create;
    begin
      FList := TList.Create;
    end;destructor TSOList.Destroy; 
    begin
      FList.Free;
      inherited;
    end;procedure TSOList.Add(so: TSO);
    begin
      FList.Add(@so);
      //这里相当于一个代理操作,下面几个类似,我便不重复叙述了
    end;
    这种方法我用了很久,虽说有些麻烦,但还是很安全。当你要用的数据结构并不多时,可以考虑
      

  8.   

    慢慢找bug吧,我对delphi的list还是比较放心,