登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> 程序员学前班[不再更新,只读] >> 主题: 服务器之王! [坛主CLQ的服务器程序开发日记,综合了众多C/C++程序崩溃的原因,强烈推荐!]     [回主站]     [分站链接]
标题
服务器之王! [坛主CLQ的服务器程序开发日记,综合了众多C/C++程序崩溃的原因,强烈推荐!]
clq
2007-2-28 15:13:47 发表 编辑


今天我们论坛程序又崩溃了一次,原因是 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
2007-2-28 15:16:48 发表 编辑

这个函数写得不精密,仅仅是为了能用而已.大家别照搬.
clq
2007-2-28 16:33:35 发表 编辑

用嵌入式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
2007-3-7 13:04:16 发表 编辑

今天又被指针晕了一次.[以下环境为纯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
2007-3-7 13:06:07 发表 编辑

这实在是个非常恐怖的问题,代码里一个不小心...难怪我们用的浏览器经常崩溃...
clq
2007-3-9 0:12:50 发表 编辑

这个问题其实很大一部分是用 char s[100] 这样的变量惯了 -- 对于它来说 f(s..) 和 f(&s..) 是一样的,而一般又习惯用前者...所以我们在使用别的类型时也惯性地这样用,而偏偏 C 语言又不报错,于是灾难发生了...
clq
2007-3-21 13:04:30 发表 编辑

前些天删除了一个NPF的模块(因为病毒太多,大清理),结果ethereal启动后发现找不到物理网卡.赶紧又找了个winpcap的包装上去,终于网卡又显示出来了.一查之下,原来NPF还挺重要,有文如下介绍
"
模块NPF(Netgroup Packet Filter),是一个虚拟设备驱动程序文件。它的功能是过滤数据包,并把这些数据包原封不动地传给用户态模块,这个过程中包括了一些操作系统特有的代码。
"

clq
2007-4-6 17:20:16 发表 编辑

两个知识点:

std::string 作为一个结构体成员,如果频繁操作消耗cpu占用是非常高的.用传统的char[]来代替则非常理想.


以前领导写的代码,想用stl代替,不过原来只锁定链表头尾的办法非常好.感觉可以结合模板思想做一个通用的线程安全高效list.



clq
2007-4-25 4:16:21 发表 编辑

delete 一个已经 delete 的指针,在linux下会立即提示段错误并崩溃.而windows+VC6 的情况下则是不会的,这实在是非常危险的事,这种情况下我倒是支持程序应该立即崩溃.

情况是这样的,我生成了一个指针交给队列,然后在清空时会出错,仔细检查后发现是我生成了一次指针的内容却向队列提交了两次,就是说队列中有两个指针是指向了同一块内存,因此释放时就会将此内存释放两次.而在vc6下这是不报错的!

再次声明,实在是危险 :( 有同事让我用智能指针 -- 我觉得那玩意更危险.

clq
2007-5-1 6:43:43 发表 编辑

刚才 apache 居然停止响应了. 呵呵,我们自己写的论坛服务器却是好好的 -- 其实不是我们写得比 apache 好,主要是 apache 追求效率程序,程序就得写得复杂,难免有bug.


我们的论坛追求的是可维护性.


总数:100 页次:5/10 首页 << 上一页 下一页  >>  尾页  
总数:100 页次:5/10 首页 << 上一页 下一页  >>  尾页  


所在合集/目录



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1