多线程任务,执行过程中,线程挂起,过段时间后进程死掉
- C/C++ code
class TBindFWD{ private: char CHANNELID[ROWCOUNT][5]; char RATECODE[ROWCOUNT][5]; char FEEDID[ROWCOUNT][5]; char FEEDBID[ROWCOUNT][15]; char FEEDASK[ROWCOUNT][15]; char FEEDMID[ROWCOUNT][15]; char VALIDFEEDBID[ROWCOUNT][15]; char VALIDFEEDASK[ROWCOUNT][15]; char VALIDFEEDMID[ROWCOUNT][15]; char BIDDELTA[ROWCOUNT][15]; char ASKDELTA[ROWCOUNT][15]; char QUOTEBID[ROWCOUNT][15]; char QUOTEASK[ROWCOUNT][15]; char QUOTEMID[ROWCOUNT][15]; char VALIDQUOTEBID[ROWCOUNT][15]; char VALIDQUOTEASK[ROWCOUNT][15]; char VALIDQUOTEMID[ROWCOUNT][15]; char BIDVOLUME[ROWCOUNT][19]; char ASKVOLUME[ROWCOUNT][19]; char TRADEMARK[ROWCOUNT][2]; char RUNSTATE[ROWCOUNT][2]; char VALUEDATE[ROWCOUNT][9]; char QUOTEBASIS[ROWCOUNT][15]; char QUOTEHIGH[ROWCOUNT][15]; char QUOTELOW[ROWCOUNT][15]; char QUOTEOPEN[ROWCOUNT][15]; char QUOTECLOSE[ROWCOUNT][15]; char REFRESHCOUNT[ROWCOUNT][9]; //char REFRESHTIME[ROWCOUNT][19]; char TERMID[ROWCOUNT][5]; // char SPOTBID[ROWCOUNT][15]; // char SPOTASK[ROWCOUNT][15]; // char SPOTMID[ROWCOUNT][15]; // char MATURITYDATE[ROWCOUNT][9]; // char CALCBID[ROWCOUNT][15]; // char CALCASK[ROWCOUNT][15]; // std::string sql; sql::TBindDefine * bd; int _rowcount; std::map<string, void *> bdmap; pricepub::TPriceFPQuoteItem item; //std::string datetimestr; public: TBindFWD(std::string bdsql); TBindFWD(); ~TBindFWD(){delete bd;}; int GetRowcount() { return _rowcount;}; std::string GetSQL() { return sql;}; sql::TBindDefine * GetBindDefine() { return bd;}; void AddItem(pricepub::TPriceFPQuoteItem item1);};//---------------------------------------TBindFWD::TBindFWD(std::string bdsql){ int fieldcount, pos; fieldcount = 0; pos = 0; while (1) { pos = bdsql.find(":bind_", pos); if (pos == std::string::npos) break; pos = pos + 6; fieldcount ++; } //fieldcount --; //std::cout << "FWD:fieldcount = " << fieldcount << std::endl; bd = new sql::TBindDefine (fieldcount); do { int pos1, pos2; pos1 = bdsql.find(":bind_"); if (pos1 == std::string::npos) break; pos2 = bdsql.find(' ', pos1+6); if (pos2 == std::string::npos) { std::cout << "Error in SQL!" << std::endl; lang::mstring mstr; mstr << "Error in SQL!"; throw lang::Exception(mstr.str());; } do { char c = bdsql[pos2-1]; if (isalpha(c)) break; else pos2 = pos2 - 1; } while (1); std::string field = bdsql.substr(pos1+6, pos2-pos1-6); field = lang::TCharSet::Upper(field); if (!strcmp(field.c_str(), "CHANNELID")) { bd->AddField((char *)CHANNELID, 5); bdmap["CHANNELID"] = (void *)(&(item.ChannelID)); } else if (!strcmp(field.c_str(), "RATECODE")) { bd->AddField((char *)RATECODE, 5); bdmap["RATECODE"] = (void *)(&(item.RateCode)); } else if (!strcmp(field.c_str(), "FEEDID")) { bd->AddField((char *)FEEDID, 5); bdmap["FEEDID"] = (void *)(&(item.FeedID)); } else if (!strcmp(field.c_str(), "FEEDBID")) { bd->AddField((char *)FEEDBID, 15); bdmap["FEEDBID"] = (void *)(&(item.FeedBid)); } else if (!strcmp(field.c_str(), "FEEDASK")) { bd->AddField((char *)FEEDASK, 15); bdmap["FEEDASK"] = (void *)(&(item.FeedAsk)); } else if (!strcmp(field.c_str(), "FEEDMID")) { bd->AddField((char *)FEEDMID, 15); bdmap["FEEDMID"] = (void *)(&(item.FeedMid)); } else if (!strcmp(field.c_str(), "VALIDFEEDBID")) { bd->AddField((char *)VALIDFEEDBID, 15); bdmap["VALIDFEEDBID"] = (void *)(&(item.ValidFeedBid)); } else if (!strcmp(field.c_str(), "VALIDFEEDASK")) { bd->AddField((char *)VALIDFEEDASK, 15); bdmap["VALIDFEEDASK"] = (void *)(&(item.ValidFeedAsk)); } else if (!strcmp(field.c_str(), "VALIDFEEDMID")) { bd->AddField((char *)VALIDFEEDMID, 15); bdmap["VALIDFEEDMID"] = (void *)(&(item.ValidFeedMid)); } else if (!strcmp(field.c_str(), "BIDDELTA")) { bd->AddField((char *)BIDDELTA, 15); bdmap["BIDDELTA"] = (void *)(&(item.BidDelta)); } else if (!strcmp(field.c_str(), "ASKDELTA")) { bd->AddField((char *)ASKDELTA, 15); bdmap["ASKDELTA"] = (void *)(&(item.AskDelta)); } else if (!strcmp(field.c_str(), "QUOTEBID")) { bd->AddField((char *)QUOTEBID, 15); bdmap["QUOTEBID"] = (void *)(&(item.QuoteBid)); } else if (!strcmp(field.c_str(), "QUOTEASK")) { bd->AddField((char *)QUOTEASK, 15); bdmap["QUOTEASK"] = (void *)(&(item.QuoteAsk)); } else if (!strcmp(field.c_str(), "QUOTEMID")) { bd->AddField((char *)QUOTEMID, 15); bdmap["QUOTEMID"] = (void *)(&(item.QuoteMid)); } else if (!strcmp(field.c_str(), "VALIDQUOTEBID")) { bd->AddField((char *)VALIDQUOTEBID, 15); bdmap["VALIDQUOTEBID"] = (void *)(&(item.ValidQuoteBid)); } else if (!strcmp(field.c_str(), "VALIDQUOTEASK")) { bd->AddField((char *)VALIDQUOTEASK, 15); bdmap["VALIDQUOTEASK"] = (void *)(&(item.ValidQuoteAsk)); } else if (!strcmp(field.c_str(), "VALIDQUOTEMID")) { bd->AddField((char *)VALIDQUOTEMID, 15); bdmap["VALIDQUOTEMID"] = (void *)(&(item.ValidQuoteMid)); } else if (!strcmp(field.c_str(), "BIDVOLUME")) { bd->AddField((char *)BIDVOLUME, 19); bdmap["BIDVOLUME"] = (void *)(&(item.BidVolume)); } else if (!strcmp(field.c_str(), "ASKVOLUME")) { bd->AddField((char *)ASKVOLUME, 19); bdmap["ASKVOLUME"] = (void *)(&(item.AskVolume)); } else if (!strcmp(field.c_str(), "TRADEMARK")) { bd->AddField((char *)TRADEMARK, 2); bdmap["TRADEMARK"] = (void *)(&(item.TradeMark)); } else if (!strcmp(field.c_str(), "RUNSTATE")) { bd->AddField((char *)RUNSTATE, 2); bdmap["RUNSTATE"] = (void *)(&(item.RunState)); } else if (!strcmp(field.c_str(), "VALUEDATE")) { bd->AddField((char *)VALUEDATE, 9); bdmap["VALUEDATE"] = (void *)(&(item.ValueDate)); } else if (!strcmp(field.c_str(), "QUOTEBASIS")) { bd->AddField((char *)QUOTEBASIS, 15); bdmap["QUOTEBASIS"] = (void *)(&(item.QuoteBasis)); } else if (!strcmp(field.c_str(), "QUOTEHIGH")) { bd->AddField((char *)QUOTEHIGH, 15); bdmap["QUOTEHIGH"] = (void *)(&(item.QuoteHigh)); } else if (!strcmp(field.c_str(), "QUOTELOW")) { bd->AddField((char *)QUOTELOW, 15); bdmap["QUOTELOW"] = (void *)(&(item.QuoteLow)); } else if (!strcmp(field.c_str(), "QUOTEOPEN")) { bd->AddField((char *)QUOTEOPEN, 15); bdmap["QUOTEOPEN"] = (void *)(&(item.QuoteOpen)); } else if (!strcmp(field.c_str(), "QUOTECLOSE")) { bd->AddField((char *)QUOTECLOSE, 15); bdmap["QUOTECLOSE"] = (void *)(&(item.QuoteClose)); } else if (!strcmp(field.c_str(), "REFRESHCOUNT")) { bd->AddField((char *)REFRESHCOUNT, 9); bdmap["REFRESHCOUNT"] = (void *)(&(item.UpdateCount)); } /* else if (!strcmp(field.c_str(), "REFRESHTIME")) { bd->AddField((char *)REFRESHTIME, 19); bdmap["REFRESHTIME"] = (void *)(&datetimestr); } */ else if (!strcmp(field.c_str(), "TERMID")) { bd->AddField((char *)TERMID, 5); bdmap["TERMID"] = (void *)(&(item.TermID)); } else if (!strcmp(field.c_str(), "SPOTBID")) { bd->AddField((char *)SPOTBID, 15); bdmap["SPOTBID"] = (void *)(&(item.SpotBid)); } else if (!strcmp(field.c_str(), "SPOTASK")) { bd->AddField((char *)SPOTASK, 15); bdmap["SPOTASK"] = (void *)(&(item.SpotAsk)); } else if (!strcmp(field.c_str(), "SPOTMID")) { bd->AddField((char *)SPOTMID, 15); bdmap["SPOTMID"] = (void *)(&(item.SpotMid)); } else if (!strcmp(field.c_str(), "MATURITYDATE")) { bd->AddField((char *)MATURITYDATE, 9); bdmap["MATURITYDATE"] = (void *)(&(item.MaturityDate)); } else { std::cout << "Error Field!" << std::endl; /* lang::mstring mstr; mstr << "Error Field!"; throw lang::Exception(mstr.str()); */ } bdsql = bdsql.erase(pos1, 6); } while (1); sql = bdsql; _rowcount = 0;}
这是我设计的类及其构造函数。
我先说说问题。这是一个多线程的服务端程序。包括mainthread, workthread, dbreadthread, dbwritethread四个线程。程序运行在Aix上。在workthread里面我通过TBindFWD *bindfwd = new TBindFWD(sqlfwd);这种方式得到一个实例。然后通过线程间调度给dbwritethread,执行完数据库语句之后,delete在workthread里面new出来的空间。
现在问题是这样的,程序执行几分钟后,workthread挂起,再过几分钟,然后整个server进程自动关闭。
因为这个服务端程序是改造项目,先前的服务端程序没有出现这样的问题,所以,我猜测是修改的代码出了问题。
另外,通过监控内存使用情况,发现,改造后的服务端程序,大概在内存占用为50M的时候自动关闭,而Aix能够承受的内存消耗是170M。并且改造前的服务端程序内存消耗达到100M的时候依然运行。
一开始我还认为是因为new出来的空间被释放后,没有被系统及时回收造成的,现在有点困惑,不确认是不是这个原因
[解决办法]
说实话看你的代码有点长,有点晕
只能逐步排除,虽然有点笨但是很有效。
程序执行几分钟后,workthread挂起,再过几分钟,然后整个server进程自动关闭。
看代码,应该和你的类本身关系不大。你的类应该是根据bdsql,最后生成一串标准的sql语句,赋值给string sql.
workthread挂起,这个是程序主动挂起(代码挂起)还是未知原因挂起?还是进程正常执行完后退出了?
如有可能的话,每个进程写个假数据测试一下,单独测试。哪个进程的代码改写的多,哪个是重点。
最好从自己的开始。
//=====================================================================================
看后面的过程应该类似于是这样的。
TBindFWD *bindfwd = new TBindFWD(sqlfwd);
dbwritethread *dbwrite = new dbwritethread;
dbwrite->Write(bindfwd->GetSQL())
//...
delete bindfwd;
delete dbwrite;
瞎给的意见
1,不清楚你们这个程序频繁度怎么样,如果很频繁这么重复的new 和 delete不太好,会造成内存碎片。
2,bdsql和sql,过于频繁如有可能参照1用个固定大小的char数组代替一下(预估一下足够大就行),先测试一下是不是这两个原因。
[解决办法]
重点检查你修改的代码看看吧,最好是输出日志看看