标题
服务器之王! [坛主CLQ的服务器程序开发日记,综合了众多C/C++程序崩溃的原因,强烈推荐!]
clq
今天我们论坛程序又崩溃了一次,原因是 mysql 的 mysql_fetch_row 函数结果行 row 中的值可能为空(NULL),而这个NULL直接赋值给 std::string 会立即崩溃!
另外还有一个郁闷的问题,用了那个版本的 mysql 库编译就要用哪一个版本的 libmySQL.dll 苍天呀!
//打开读取一个mysql表
bool open_mysql_sql(std::string sql, std::string id_field_name)
{
MYSQL mysql;
MYSQL_RES * result;
MYSQL_ROW row;
int num_fields;//字段个数
int i;
int line_id = 0;//行号
unsigned long *lengths;//当前行的字段值长度
MYSQL_FIELD *fields;//字段属性
std::string key = "";
std::string value = "";
...
if ( mysql_query(&mysql, (sql).c_str() ) !=0 )
{
printf("mysql_query error:%s\n", mysql_error(&mysql));
}
//result = mysql_use_result(&mysql);
result = mysql_store_result(&mysql);
//用 mysql_store_result 更好
//用 mysql_fetch_lengths 得到行的各个长度
//printf (Number of rows: %lu\n", (unsigned long) mysql_num_rows(result));
//遍历各行
while((row = mysql_fetch_row(result)))
{
// do something with data
//得到字段的个数
num_fields = mysql_num_fields(result);
//得到各个行的长度[注意这对各行的值是不同的]
lengths = mysql_fetch_lengths(result);
//得到字段名
fields = mysql_fetch_fields(result);
//printf("%s\r\n", row[0]);
keys * k = new keys();//keys会被容器自动销毁的
//遍历各字段
for(i = 0; i < num_fields; i++)
{
//printf("Column %u is %lu bytes in length.\n", i, lengths[i]);
//printf("Field %u is %s\n", i, fields[i].name);
key = fields[i].name;//字段名
//value = row[i];//字段值
if (row[i] == NULL)
{
value = "";
}
else
{
value = row[i];//字段值
}
(*k)[key] = value;
continue;
}
//std::string id = get_value((*k), "id");//主键
std::string id = get_value((*k), id_field_name);//主键
if (trim(id).length()==0)
{
continue;
}
//(*k)["line_id"] = int_to_str(line_id);//人为加一个行号
(*k)["line_id"] = int_to_str(line_id, 8);//人为加一个行号
//加入到最后的数据集中
//this->set_line(id, k, false);
this->set_line((*k)["line_id"], k, false);
line_id++;//行号
}
mysql_free_result(result);//一定要释放
//printf("ok!\n");
mysql_close(&mysql);
return true;
}
clq
这个函数写得不精密,仅仅是为了能用而已.大家别照搬.
clq
用嵌入式MySQL服务器库代替 sqlite?
偶然看到最新的 mysql 官方文档(http://dev.mysql.com/doc/refman/5.1/zh/apis.html),发现它多出了这样功能.不过它的许可...能用在商业方面吗?
25.1. libmysqld,嵌入式MySQL服务器库
25.1.1. 嵌入式MySQL服务器库概述
25.1.2. 使用libmysqld编译程序
25.1.3. 使用嵌入式MySQL服务器时的限制
25.1.4. 与嵌入式服务器一起使用的选项
25.1.5. 嵌入式服务器中尚需完成的事项(TODO)
25.1.6. 嵌入式服务器示例
25.1.7. 嵌入式服务器的许可
25.1.1. 嵌入式MySQL服务器库概述
使用嵌入式MySQL服务器库,能够在客户端应用程序中使用具备全部特性的MySQL服务器。 主要优点在于,增加了速度,并使得嵌入式应用程序的管理更简单。
嵌入式服务器库是以MySQL的客户端/服务器版本为基础的,采用C/C++语言编写。 其结果是嵌入式服务器也是用C/C++语言编写的。 在其他语言中,嵌入式服务器不可用。
API与嵌入式MySQL版本和客户端/服务器版本等效。 要想更改旧的线程式应用程序以使用嵌入式库,正常情况下,仅需添加对下述函数的调用即可。
函数
何时调用
mysql_server_init()
应在调用任何其他MySQL函数之前调用,最好是在main()函数中调用。
mysql_server_end()
应在程序退出前调用。
mysql_thread_init()
应在你所创建的、用于访问MySQL的每个线程中调用。
mysql_thread_end()
应在调用pthread_exit()之前调用。
随后,必须将你的代码与libmysqld.a链接起来,而不是libmysqlclient.a。
在libmysqlclient.a中还包含mysql_server_xxx()函数,使用这类函数,通过将应用程序链接到恰当的库,即可在嵌入式版本和客户端/服务器版本之间切换。 请参见25.2.12.1节,“mysql_server_init()”。
嵌入式服务器和独立服务器之间的一项差别在于,对于嵌入式服务器,默认情况下,连接鉴定是禁止的。 对于嵌入式服务器,要想使用鉴定功能,可在激活“configure”以配置MySQL分发版时使用“--with-embedded-privilege-control”选项。
clq
今天又被指针晕了一次.[以下环境为纯C]
结构
typedef struct stru_preAssoc{
u32 CSID;
struct stru_preAssoc *next;
}PreAssocDataType;
在 strncpy(pPreAssocPacket->CSID, pValueList->pAttrValue, 4) 时出错,而且只是vc6的debug状态下出错,直接点击"!"图标运行是不出错的.
修改为
typedef struct stru_preAssoc{
u8 CSID[6];
struct stru_preAssoc *next;
}PreAssocDataType;
就OK.我想是不是strncpy越界了,改小了复制字节数或用memcpy代替均失败.
最后得是这样
memcpy(&(pPreAssocPacket->CSID), pValueList->pAttrValue, 4)
原因是兄弟我一看 "->" 号就以为是指针了,其实这里操作的仍然是数值本身(变量本身).而C语言是两种都可编译通过的,只是按这个数值当做指针去找一个空间,而这个空间肯定不是CSID本身的,所以就出错.
不过直接运行为什么不报错? 一定要是调试状态才出错? 以前有文章介绍VC6的debug版本与release版本的不同之处,看来还得搞清楚,debug版本在调试与直接运行之间的不同之处...
clq
这实在是个非常恐怖的问题,代码里一个不小心...难怪我们用的浏览器经常崩溃...
clq
这个问题其实很大一部分是用 char s[100] 这样的变量惯了 -- 对于它来说 f(s..) 和 f(&s..) 是一样的,而一般又习惯用前者...所以我们在使用别的类型时也惯性地这样用,而偏偏 C 语言又不报错,于是灾难发生了...
clq
前些天删除了一个NPF的模块(因为病毒太多,大清理),结果ethereal启动后发现找不到物理网卡.赶紧又找了个winpcap的包装上去,终于网卡又显示出来了.一查之下,原来NPF还挺重要,有文如下介绍
"
模块NPF(Netgroup Packet Filter),是一个虚拟设备驱动程序文件。它的功能是过滤数据包,并把这些数据包原封不动地传给用户态模块,这个过程中包括了一些操作系统特有的代码。
"
clq
两个知识点:
std::string 作为一个结构体成员,如果频繁操作消耗cpu占用是非常高的.用传统的char[]来代替则非常理想.
以前领导写的代码,想用stl代替,不过原来只锁定链表头尾的办法非常好.感觉可以结合模板思想做一个通用的线程安全高效list.
clq
delete 一个已经 delete 的指针,在linux下会立即提示段错误并崩溃.而windows+VC6 的情况下则是不会的,这实在是非常危险的事,这种情况下我倒是支持程序应该立即崩溃.
情况是这样的,我生成了一个指针交给队列,然后在清空时会出错,仔细检查后发现是我生成了一次指针的内容却向队列提交了两次,就是说队列中有两个指针是指向了同一块内存,因此释放时就会将此内存释放两次.而在vc6下这是不报错的!
再次声明,实在是危险 :( 有同事让我用智能指针 -- 我觉得那玩意更危险.
clq
刚才 apache 居然停止响应了. 呵呵,我们自己写的论坛服务器却是好好的 -- 其实不是我们写得比 apache 好,主要是 apache 追求效率程序,程序就得写得复杂,难免有bug.
我们的论坛追求的是可维护性.
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.