问题:在做C#程序时,既然发生[StringBuilder 溢出]
详情如下:
   引发类型为“System.OutOfMemoryException”的异常。
   在 System.String.GetStringForStringBuilder(String value, Int32 startIndex, Int32 length, Int32 capacity)
   在 System.Text.StringBuilder.GetNewString(String currentString, Int32 requiredLength)
   在 System.Text.StringBuilder.Append(String value)
原因:在调用下面的方法时,有时会产生上面的问题,有时则不会可以保证的是每一次的数据量是不足于产生于溢出环境:
windows2003
CPU:4核,
内存:6G (运行时只使用不到3G内存),
SQL2005数据库。
取数的表数在1000左右,数据量在1.6G左右(每次只取30-50M的数据量
public class StartClass
{
    /// <summary>
    /// 该方法可能是个事件,在特定的条件下会执行
    ///数据量在1.6G左右(但每次只取30-50M的数据量)
    /// </summary>
    public void Main()
    {
        MyTest mt = new MyTest();
        mt.StartMethod();
    }
}public class MyTest
{
    public void StartMethod()
    {
        //得到所有表的SQL数据脚本
        List<string> _list = new List<string>();
        //生成xml文件保存
        XmlDocument xml = new XmlDocument();
        //(省略...)
        xml.Save("C:\\tmp.xml");
        
    }
    /// <summary>
    /// 生成所有表的SQL数据脚本
    /// </summary>
    /// <returns></returns>
    private List<string> GetList()
    {
        List<string> _list = new List<string>();
        //得到所有表的名称
        DataTable dt = this .GetAllTableName ();
        //下面是得到一个表数据的全部SQL数据脚本
        foreach (DataRow dr in dt.Rows)
        {
            //得到表名
            string tableName = dr["tableName"].ToString();
            DataTable dtData = this.GetTableData(tableName);
            //下面是得到单行数据的SQL数据脚本 
            StringBuilder sb = new StringBuilder();
            foreach (DataRow drData in dtData)
            {
                //这里可能会报"内存溢出";
                sb.Append("insert into [表名]('字段名_1','字段名_2','字段名_3','字段名_N') values ('值_1','值_2','值_3','值_N');\r\n");
            }
            //将每个表的SQL数据脚本加到list中去
            _list.Add(sb.ToString());
        }
        return _list;
    }
    /// <summary>
    /// 得到所有合适表的名称
    /// </summary>
    /// <returns></returns>
    private DataTable GetAllTableName()
    {
        DataTable dt = new DataTable();
        return dt;
    }
    /// <summary>
    /// 得到该表中的全部数据
    /// </summary>
    /// <param name="tableName"></param>
    /// <returns></returns>
    private DataTable GetTableData(string tableName)
    {
        DataTable dt = new DataTable();
        return dt;
    }
}祝:七七节快乐,送77分咯 *_*

解决方案 »

  1.   

    虽然你有 6G,但是 String 理论上只能用最大接近 2G
      

  2.   

    OutOfMemoryException是内存不足,监视一下程序占用内存的情况。
      

  3.   

    sb.Append("insert into [表名]('字段名_1','字段名_2','字段名_3','字段名_N') values ('值_1','值_2','值_3','值_N');\r\n");
    1、考虑将该句拆分为多句,以便更精确定位错误所在;
    2、将出错时sb.ToString()的值记录,仔细研究有什么特点;
    3、换其他表试试看;
    4、换其他机器试试看。
      

  4.   

    有说法是StringBuilder会引起内存碎片,建议使用MemoryStream代替,不知道效果如何。
      

  5.   

    建议楼主单步调试跟下代码,你看下你的Rows.Count是多少,估计出现死循环了
      

  6.   

    这应该是堆分配连续控件的限制,可以考虑用多个stringbuilder试试。
      

  7.   


    是这样的,但是我每次只取了30-40G的数据量的(60W时间戳的内容)
    所以每次的运行量不会超过2G的
      

  8.   


    Rows.Count是很多的,大概在60W-120W左右的
      

  9.   

    //将每个表的SQL数据脚本加到list中去
    list.Add(sb.ToString());
    在这里当使用完sb之后顺手加一行清除sb所有内容的语句,有点多余,不过多点保障,不妨试试,搞不好内存就不再益处了呢,呵呵.
      

  10.   

    1.每次运行程序的时候不一定都会溢出
    2.单次运行的时候不会溢出。
    所以是不是这样子的:
    1.stringBulider是在每次运行之后没有释放点原占有的内存?
    2.是不是stringBulider是值copy 因为我可能要append在几十万次的 而导致错误..
      

  11.   


    这里的sb.Tostring()会不会有个问题
      

  12.   


    是在sb.Tostring()之后才清除sb啊,看不出问题.
      

  13.   

    如果StringBuilder除了Append之外没有其他的操作,还是可以用MemoryStream代替的。
      

  14.   

    32bit下单个App只能用到2G内存,OutOfMemoryException你看下你的那个程序,内存占用应该是接近2GB了。
      

  15.   

    StringBuilder 实例 会占用大量内存。你是要把一个表的数据存放到另一个表吗?那你编写代码的效率简直太低了,先优化sql吧
      

  16.   

     foreach (DataRow dr in dt.Rows)
            {
                //得到表名
                string tableName = dr["tableName"].ToString();
                DataTable dtData = this.GetTableData(tableName);
                //下面是得到单行数据的SQL数据脚本 
                StringBuilder sb = new StringBuilder();
                foreach (DataRow drData in dtData)
                {
                    //这里可能会报"内存溢出";
                    sb.Append("insert into [表名]('字段名_1','字段名_2','字段名_3','字段名_N') values ('值_1','值_2','值_3','值_N');\r\n");
                }
                //将每个表的SQL数据脚本加到list中去
                _list.Add(sb.ToString());
            }
            return _list;你用了大量StringBulder 实例,在return前调用垃圾收集器帮你清理下。System.GC.Collect();
      

  17.   

    StringBuilder sb = new StringBuilder();
    这个初始化sb有长度限制的,如果你要加长的字符可以这样初始化
    StringBuilder sb = new StringBuilder(10240);
    这样sb的字符装载量有10240个,应该不会超了吧,根据实际长度来设置初始化的数值