代码如下:
    objMemoryRelation.Position := 0;
    SetLength(str, objMemoryRelation.Size); //这里超过1亿个字符长度,出现内存Out错误,
    objMemoryRelation.ReadBuffer(str[1], objMemoryRelation.Size);
    StrRelations := str; 
    SetLength(str, 0); //这里进行内存释放,但是好像没有用。请各位大侠提供办法,多谢!。

解决方案 »

  1.   

    SetLength,第二个长度参数是integer,他的容量是有限的SetLength(str, 0),效果不一定就能立即看到
      

  2.   

    可以现在我们的业务需要有这么长的字符串了,直接用字符串进行拼接,已经出现了内存耗尽的错误。
    现在改为用流来处理,但是又遇到这个问题。大家有没有什么好的办法处理大的字符串拼接,可能会超过1G(虽然帮助上说String不会超过2G,但内存会耗尽的)
    如果用文本来处理呢?
      

  3.   

    可以现在我们的业务需要有这么长的字符串了,直接用字符串进行拼接,已经出现了内存耗尽的错误。
    现在改为用流来处理,但是又遇到这个问题。大家有没有什么好的办法处理大的字符串拼接,可能会超过1G(虽然帮助上说String不会超过2G,但内存会耗尽的)
    如果用文本来处理呢?
      

  4.   

    SetLength(*, 0)的效果马上就能看到
      

  5.   

    Debug时已经查看了,大概是1亿个字符,申请的时候失败了。
    关键是,处理这种字符串还是在循环中处理,所以这个问题必现。
    如果用文本文件来处理存储字符串,然后再读取到字符串中,会不会也出现这种问题呢?
    多谢。请各位提供解决方法。
      

  6.   

    那你说说为什么不会马上看到效果吧,是不调用FreeMem么,还是delphi的内存管理器不会回收这么大的地址,还是windows内核不会马上回收这么多空页面?
      

  7.   

       objMemoryRelation.Position := 0; 
        SetLength(str, objMemoryRelation.Size); //这里超过1亿个字符长度,出现内存Out错误, 
        objMemoryRelation.ReadBuffer(str[1], objMemoryRelation.Size); 
        StrRelations := str; // 這句是處理哪些的。感覺是這裏吧。
        SetLength(str, 0); 我有點不明白,如 Sermour  所說的。1億字符 100M左右。也就是你沒次 SetLength  申請 100M左邊的內存,使用後再釋放掉,這也應該沒什麼問題StrRelations := str; // 這句是處理哪些的。另外你上面這段就是放在循環裏面的?? 代碼越看越不明白了。If there is not enough memory available to reallocate the variable, SetLength raises an EOutOfMemory exception.  SetLength內存不足就出上面的錯誤,你應該把問題的關鍵放在解決每次將這100M傳給StrRelations 後怎麼辦。不能一直這樣增加下去吧。
      

  8.   

    没有将完整的代码贴出来的,循环部分包含了我们的业务处理部分,StrRelations := str; 这里是Var的变量,在循环体中是有使用的。
    肯定是内存申请不够造成的。
      

  9.   


    DELPHI  STRING的方式對於你這種情況,只是增加了str的引用計數,所以: SetLength(str, 0); 不會因為你的這句話而釋放掉,因為當前這塊內存還有StrRelations 在引用
      

  10.   

    那不和Java的内存释放规则是一样的,如果没有被引用才去考虑释放?
    郁闷,看来用流和字符串都不能解决这个问题,我查下程序有没有优化的空间。如果用文本文件来处理的话,同样需要读到数据到字符串中,我估计不会解决问题,大家认为呢?
      

  11.   

    delphi  string 與STRING之間  並不用到 Copy  只是增加引用計數回收效果與JAVA有點相同,STRING也是分配在堆上。 通過此用計數來管理。
      

  12.   


    嘻嘻,看来Seamour是个教师哟,本科学的比较烂啊。
    用外存进行处理,还是第一次听说哈。可否讲下思路也,也让俺开下眼界?拜谢。
      

  13.   

    操作系統上也有說過,不過運用這些,效率就會慢下來
    我覺得如果循環調用的時候是VAR 引用返回的字符串。SETLENGTH 一次就申請一個足夠大的。然後在循環中使用,只是更新,就沒有必要每次都申請了,不過這樣的做法比較有局限性。
    Seamour 在操作系統這塊的理解是挺強的。
      

  14.   

       objMemoryRelation.Position := 0; 
        SetLength(str, objMemoryRelation.Size); //这里超过1亿个字符长度,出现内存Out错误, 
        objMemoryRelation.ReadBuffer(str[1], objMemoryRelation.Size); 
        StrRelations := str; // 這句是處理哪些的。感覺是這裏吧。
        SetLength(str, 0); 
    StrRelations := str;//为内存增加一个引用计数
    SetLength(str, 0);//减少上面内存的引用计数,并且为str重新分配了内存。所以由于StrRelations 还在引用该内存(除非后面没有使用StrRelations,而由编译器的优化功能做出了优化处理,删除了该字符串)
      

  15.   


    我也覺得是這樣的,由於引用的問題。而且他的空間在循環中申請,所以內存不足應該不是第一次申請空間,而是多次循環後出現的。StrRelations 這應該是在函數中VAR 引用的。
    我的建議是:把SetLength 放在最外面,一次比較大的內存。只更新STR,而不要去不斷申請內存。我對這塊理解也不是很深。 還請僵哥指教
      

  16.   

    单凭他贴出来的这两句代码谁也说不清楚问题出在哪里。碰到的更多的情况是程序上面的问题,导致内存泄露,从而一再强调代码上如何如何没有太多的使用内存却会报出内存不足的异常。就好比楼主的objMemoryRelation,这个在上面的代码当中能够大概地判断是一个Stream,具体是不是TMemoryStream就不得而知。假定是TMemoryStream,那么就会存在一个问题,这1亿个字符就在内存存在了两份,那为什么一开始要存储到了TMemoryStream当中而不直接放到String,或者不直接在TmemoryStream.Memory当中处理?
      

  17.   


    为什么试用TMemoryStream是:
    由于String在大量拼接时出现EOutOfMemory exception异常造成的,才考虑用流来处理。现在我把代码做了优化,去掉了部分重复的内容,以达到时间换空间的目的。
    问题到是解决了。
    感谢各位专家的指点,再次谢谢。同时欢迎各位再次针对类似的问题进行讨论,分析。
      

  18.   

    其实String也可以象MemoryStream那样使用,先预分配足够的内存空间,然后使用move进行数据的复制,而不是string= string+ string
      

  19.   

    原理都是一样的啊,无非都是分制的思路,然后看怎么做才能尽量少的进行内外存的数据交换另,string也可以用TStringStream