帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

how to create a class , which size is 0?

If you create a class with array [0], you have done it.😄

Only in gcc compiler…in visual c++6.0, it is still 1.

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
using namespace std;
class A
{
char a[0];
};
int main()
{
cout << sizeof(A);
return 0;
}

引用地址: [ http://free.yes81.net/yes81/view-1179.html

](http://free.yes81.net/yes81/view-1179.html)

crontab 命令

功能是在一定的时间间隔调度一些命令的执行。在 /etc 目录下有一个 crontab
文件,这里存放有系统运行的一些调度程序。每个用户可以建立自己的调度 crontab 。
crontab 命令有三种形式的命令行结构:
crontab [-u user] [file]
crontab [-u user] [-e|-l|-r]
crontab -l -u [-e|-l|-r]
第一个命令行中, file 是命令文件的名字。如果在命令行中指定了这个文件,那么执行 crontab 命令,则将这个文件拷贝到 crontabs
目录下;如果在命令行中没有制定这个文件, crontab 命令将接受标准输入(键盘)上键入的命令,并将他们也存放在 crontab 目录下。
命令行中 -r 选项的作用是从 /usr/spool/cron/crontabs 目录下删除用户定义的文件 crontab ;
命令行中 -l 选项的作用是显示用户 crontab 文件的内容。
使用命令 crontab -u user -e 命令编辑用户 user 的 cron© 作业。用户通过编辑文件来增加或修改任何作业请求。
执行命令 crontab -u user -r 即可删除当前用户的所有的 cron 作业。
作业与它们预定的时间储存在文件 /usr/spool/cron/crontabs/username 里。 username
使用户名,在相应的文件中存放着该用户所要运行的命令。命令执行的结果,无论是标准输出还是错误输出,都将以邮件形式发给用户。文件里的每一个请求必须包含以
spaces 和 tabs 分割的六个域。前五个字段可以取整数值,指定何时开始工作,第六个域是字符串,称为命令字段,其中包括了 crontab
调度执行的命令。
第一道第五个字段的整数取值范围及意义是:
0 ~ 59 表示分
1 ~ 23 表示小时
1 ~ 31 表示日
1 ~ 12 表示月份
0 ~ 6 表示星期(其中 0 表示星期日)
/usr/lib/cron/cron.allow 表示谁能使用 crontab
命令。如果它是一个空文件表明没有一个用户能安排作业。如果这个文件不存在,而有另外一个文件 /usr/lib/cron/cron.deny,
则只有不包括在这个文件中的用户才可以使用 crontab 命令。如果它是一个空文件表明任何用户都可安排作业。两个文件同时存在时 cron.allow
优先,如果都不存在,只有超级用户可以安排作业。
任务调度的 crond 常驻命令
crond 是 linux 用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。 crond
命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。而 linux 任务调度的工作主要分为以下两类:
1 、系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存
2 、个人执行的工作:某个用户定期要做的工作,例如每隔 10 分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置。
一、任务调度设置文件的写法
其格式如下:
Minute Hour Day Month Dayofweek command
分钟 小时 天 月 天每星期 命令
每个字段代表的含义如下:
Minute 每个小时的第几分钟执行该任务
Hour 每天的第几个小时执行该任务
Day 每月的第几天执行该任务
Month 每年的第几个月执行该任务
DayOfWeek 每周的第几天执行该任务
Command 指定要执行的程序
在这些字段里,除了“ Command ”是每次都必须指定的字段以外,其它字段皆为可选字段,可视需要决定。对于不指定的字段,要用“ *
”来填补其位置。
举例如下:
1 、指定每小时的第 5 分钟执行一次 ls 命令
5 * * * * ls
2 、指定每天的 5:30 执行 ls 命令
30 5 * * * ls
3 、指定每月 8 号的 7 : 30 分执行 ls 命令
30 7 8 * * ls
4 、指定每年的 6 月 8 日 5 : 30 执行 ls 命令
30 5 8 6 * ls
5 、指定每星期日的 6:30 执行 ls 命令
30 6 * * 0 ls
注: 0 表示星期天, 1 表示星期 1 ,以此类推,也可以用英文来表示, sun 表示星期天, mon 表示星期一等。
6 、每月 10 号及 20 号的 3 : 30 执行 ls 命令
30 3 10,20 * * ls
注:“,”用来连接多个不连续的时段
7 、每天 8-11 点的第 25 分钟执行 ls 命令
25 8-11 * * * ls
注:“ - ”用来连接连续的时段
8 、每 15 分钟执行一次 ls 命令
*/15 * * * * ls
即每个小时的第 0 15 30 45 60 分钟执行 ls 命令
9 、每个月中,每隔 10 天 6:30 执行一次 ls 命令
30 6 */10 * * ls
即每月的 1 、 11 、 21 、 31 日是的 6 : 30 执行一次 ls 命令。
10 、每天 7 : 50 以 root 身份执行 /etc/cron.daily 目录中的所有可执行文件
50 7 * * * root run-parts /etc/cron.daily
注: run-parts 参数表示,执行后面目录中的所有可执行文件。
二、新增调度任务
新增调度任务可用两种方法:
1 、在命令行输入 : crontab -e 然后添加相应的任务, wq 存盘退出。
2 、直接编辑 /etc/crontab 文件,即 vi /etc/crontab ,添加相应的任务。
三、查看调度任务
crontab -l // 列出当前的所有调度任务
crontab -l -u jp    // 列出用户 jp 的所有调度任务
四、删除任务调度工作
crontab -r // 删除所有任务调度工作
五、任务调度执行结果的转向
例 1 :每天 5 : 30 执行 ls 命令,并把结果输出到 /jp/test 文件中
30 5 * * * ls >/jp/test 2>&1
注: 2>&1 表示执行结果及错误信息。
编辑 /etc/crontab 文件配置 cron
cron 服务每分钟不仅要读一次 /var/spool/cron 内的所有文件,还需要读一次 /etc/crontab,
因此我们配置这个文件也能运用 cron 服务做一些事情。用 crontab 配置是针对某个用户的,而编辑 /etc/crontab
是针对系统的任务。此文件的文件格式是 :
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root // 如果出现错误,或者有数据输出,数据作为邮件发给这个帐号
HOME=/ // 使用者运行的路径 , 这里是根目录

run-parts

01 * * * * root run-parts /etc/cron.hourly // 每小时执行 /etc/cron.hourly 内的脚本
02 4 * * * root run-parts /etc/cron.daily // 每天执行 /etc/cron.daily 内的脚本
22 4 * * 0 root run-parts /etc/cron.weekly // 每星期执行 /etc/cron.weekly 内的脚本
42 4 1 * * root run-parts /etc/cron.monthly // 每月去执行 /etc/cron.monthly 内的脚本
大家注意 “run-parts” 这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是文件夹名了

以下转自鸟哥私房菜

http://linux.vbird.org/linux_basic/0430cron.php#at
單一工作排程的進行就使用 at 這個指令囉!這個指令的運作非常簡單!將 at 加上一個時間即可!基本的語法如下:

[root@www ~]# at [-mldv] TIME

[root@www ~]# at -c 工作號碼

選項與參數:
-m  :當 at 的工作完成後,即使沒有輸出訊息,亦以 email 通知使用者該工作已完成。
-l  :at -l 相當於 atq,列出目前系統上面的所有該使用者的 at 排程;
-d  :at -d 相當於 atrm ,可以取消一個在 at 排程中的工作;
-v  :可以使用較明顯的時間格式列出 at 排程中的工作列表;
-c  :可以列出後面接的該項工作的實際指令內容。

TIME:時間格式,這裡可以定義出『什麼時候要進行 at 這項工作』的時間,格式有:
  HH:MM				ex> 04:00
	在今日的 HH:MM 時刻進行,若該時刻已超過,則明天的 HH:MM 進行此工作。
  HH:MM YYYY-MM-DD		ex> 04:00 2009-03-17
	強制規定在某年某月的某一天的特殊時刻進行該工作!
  HH:MM[am|pm] [Month] [Date]	ex> 04pm March 17
	也是一樣,強制在某年某月某日的某時刻進行!
  HH:MM[am|pm] + number [minutes|hours|days|weeks]
	ex> now + 5 minutes	ex> 04pm + 3 days
	就是說,在某個時間點『再加幾個時間後』才進行。

老實說,這個 at 指令的下達最重要的地方在於『時間』的指定了!鳥哥喜歡使用『 now + … 』
的方式來定義現在過多少時間再進行工作,但有時也需要定義特定的時間點來進行!底下的範例先看看囉!

範例一:再過五分鐘後,將 /root/.bashrc 寄給 root 自己

[root@www ~]# at now + 5 minutes
  <==記得單位要加 s 喔!

at> /bin/mail root -s "testing at job" < /root/.bashrc

at> <EOT>   <==這裡輸入 [ctrl] + d 就會出現 <EOF> 的字樣!代表結束!

job 4 at 2009-03-14 15:38
# 上面這行資訊在說明,第 4 個 at 工作將在 2009/03/14 的 15:38 進行!
# 而執行 at 會進入所謂的 at shell 環境,讓你下達多重指令等待運作!
範例二:將上述的第 4 項工作內容列出來查閱

[root@www ~]# at -c 4

#!/bin/sh               <==就是透過 bash shell 的啦!

# atrun uid=0 gid=0
# mail     root 0
umask 22
....(中間省略許多的環境變數項目)....

cd /root || {           <==可以看出,會到下達 at 時的工作目錄去執行指令

         echo 'Execution directory inaccessible' >&2
         exit 1
}

/bin/mail root -s "testing at job" < /root/.bashrc
# 你可以看到指令執行的目錄 (/root),還有多個環境變數與實際的指令內容啦!
範例三:由於機房預計於 2009/03/18 停電,我想要在 2009/03/17 23:00 關機?

[root@www ~]# at 23:00 2009-03-17

at> /bin/sync

at> /bin/sync

at> /sbin/shutdown -h now

at> <EOT>
job 5 at 2009-03-17 23:00
# 您瞧瞧! at 還可以在一個工作內輸入多個指令呢!不錯吧!

事實上,當我們使用 at 時會進入一個 at shell 的環境來讓使用者下達工作指令,此時, 建議你最好使用絕對路徑來下達你的指令,比較不會有問題喔
!由於指令的下達與 PATH 變數有關, 同時與當時的工作目錄也有關連 (如果有牽涉到檔案的話),因此使用絕對路徑來下達指令,會是比較一勞永逸的方法。
為什麼呢?舉例來說,你在 /tmp 下達『 at now 』然後輸入『 mail root -s “test” < .bashrc 』, 問一下,那個
.bashrc 的檔案會是在哪裡?答案是『 /tmp/.bashrc 』!因為 at 在運作時,會跑到當時下達 at 指令的那個工作目錄 的緣故啊!

有些朋友會希望『我要在某某時刻,在我的終端機顯示出 Hello 的字樣』,然後就在 at 裡面下達這樣的資訊『 echo “Hello”
』。等到時間到了,卻發現沒有任何訊息在螢幕上顯示,這是啥原因啊? 這是因為 at 的執行與終端機環境無關,而所有 standard
output/standard error output 都會傳送到執行者的 mailbox 去 啦!所以在終端機當然看不到任何資訊。那怎辦?沒關係,
可以透過終端機的裝置來處理!假如你在 tty1 登入,則可以使用『 echo “Hello” > /dev/tty1 』來取代。

** Tips: **
要注意的是,如果在 at shell 內的指令並沒有任何的訊息輸出,那麼 at 預設不會發 email 給執行者的。 如果你想要讓 at 無論如何都發一封
email 告知你是否執行了指令,那麼可以使用『 at -m 時間格式 』來下達指令喔! at 就會傳送一個訊息給執行者,而不論該指令執行有無訊息輸出了!

at 有另外一個很棒的優點,那就是『背景執行』的功能了!什麼是背景執行啊?很難瞭解嗎?其實與 bash 的 nohup ( 第十七章
) 類似啦!
鳥哥提我自己的幾個例子來給您聽聽,您就瞭了!

  • 離線繼續工作的任務 :鳥哥初次接觸 Unix 為的是要跑空氣品質模式, 那是一種大型的程式,這個程式在當時的硬體底下跑,一個案例要跑 3 天!由於鳥哥也要進行其他研究工作,因此常常使用 Windows 98 來連線到 Unix 工作站跑那個 3 天的案例!結果你也該知道, Windows 98 連開三天而不當機的機率是很低的~@_@~ 而當機時,所有在 Windows 上的連線都會中斷!包括鳥哥在跑的那個程式也中斷了~嗚嗚~明明再三個鐘頭就跑完的程式, 由於當機害我又得跑 3 天!

  • 另一個常用的時刻則是例如上面的範例三,由於某個突發狀況導致你必須要進行某項工作時,這個 at 就很好用啦!

由於 at 工作排程的使用上,系統會將該項 at 工作獨立出你的 bash 環境中, 直接交給系統的 atd 程式來接管,因此,當你下達了 at
的工作之後就可以立刻離線了, 剩下的工作就完全交給 Linux 管理即可 !所以囉,如果有長時間的網路工作時,嘿嘿! 使用 at
可以讓你免除網路斷線後的困擾喔! _

老姐在东北完成婚礼…然后准备在家乡摆个婚宴。

因为老姐的缘故,有幸逛了下喀左。北方的小镇,风还是蛮舒服的。因为工业不发达,所以很适合人类居住。小镇很好,大概走路也就是30分钟就可以贯穿整个小镇。这个时间
只够我从软件所走到计算所。

婚礼蛮成功的,特别是老姐和姐夫自己做的flash,效果很不错。当然婚礼中还有几处细节不尽人意。1,烟花不那么容易点着。2,荧光水没有将心形容器灌满。彩排了多
次,紧张还是在所难免。不过氛围很好,很煽情:)值得一提的是,老姐那天灰常漂亮~

整个旅程唯一不足的是,叔每次都喝多,而且还打呼噜…我实在难以入睡。

最近做了下宽字符,窄字符的实验。发现了一系列的有趣东东。我发现我过去一直使用Ascii编码。现在发现unicode还是灰常有用的。

首先std::string std::wstring 和CString 这几个东东最好不要用于DLL的接口之中,不管是返回值还是传入的参数。当然编译时是不会
出错的,但是链接可能会有各种奇异的问题,比如不能识别CString等等。所以建议DLL接口还是使用LPCTSTR LPCSTR
LPCWSTR以及我们经常使用的char*. 反正是DLL接口中的类型越基础也好。当然你可以尝试使用复合类型。

这里的的LPCTSTR 就是const TCHAR , LPCSTR 就是const char , LPCWSTR就是 const
wchar_t*。LP就是指针的意思,C就是const,T就是TCHAR, W就是wchar_t, 然后大家都有STR的后缀。关于TCHAR,char,
以及wchar_t之间的关系,其实看你是否定义了_UNICODE宏,想要定义的话需要在编译的时候添加编译参数-
D_UNICODE即可。如果定义了这个宏,那么wchar_t就是TCHAR, 否则 TCHAR就是
char,其实这里就是为了灵活性。对于vs系列,想要识别unicode编码,需要在字符或者字符串前添加L,例如:

wchar_t a = L’a’; wchar_t *b = L"abc";

关于_T()的使用,或许就明了了,_T(“ab”) 就是L"ab" , _T(‘c’) 就是 L’c’, _T(x)的宏定义就是 L ## x,其意思就是将
L和x像字符串一样连接在一起。关于宏定义的各种用法,感兴趣的可以search.当然为了灵活性,这里也是使用了_T也有两个定义这个也与是否定义了_UNICOD
E宏有关系。

所谓窄字符其实就是ascii字符,这个东东只有1个字节。而宽字符有2个字节。这就是宽字和窄字的不同了。当然这里还有WORD和DWORD,这里的WORD其实就
是unsigned short,就是2个字节和wchar_t一样。而DWORD就是unsigned
long也就是4字节。根据特殊的应用,有不同的效果。不过说到底还是各种基础类型转来转去的。

关于各种类型的互相转换其实不是很简单,不过大都可以通过CString来转换。各种窄字符可以直接放入到CString构造函数中,它将自动的为所有的字符添加L.
让其成为unicode. 例如

const char * a = “abc”; CString s(a);

其实CString可以强制转换为LPCTSTR,如果想强制转换为其他的类型,最好考虑下是否有后遗症。但是强转为LPCTSTR是没有问题的。另外std::ws
tring本身是有wchar_t的数组构成的。而std::string本身是有char数组构成的。对于这些类型只需要调用
c_str()就可以转变为const wchar_t* 或者 const char*.另外因为string,wstring, CString这几个东东都有引
用计数的机制,所以在多线程编程中,尽量不要使用。另外对于CString而言,这个东西可以强制不使用引用计数机制,只需要调用lockBuffer即可。另外CS
tring转char* 如果是在Atl编程的情况下可以使用T2A()这个函数,对于其他可以调用WideCharToMultiByte()这个函数:

WideCharToMultiByte( __in UINT CodePage, __in DWORD dwFlags, __in_opt LPCWSTR
lpWideCharStr, __in int cchWideChar, __out_bcount_opt(cbMultiByte) LPSTR
lpMultiByteStr, __in int cbMultiByte, __in_opt LPCSTR lpDefaultChar, __out_opt
LPBOOL lpUsedDefaultChar);

这个东东有8个参数,不过一般你如果使用TCHAR* 转 char* 只需要使用其中的若干个。一般使用:WideCharToMultiByte(CP_ACP,
0, lpw, -1, lpa, nChars, NULL, NULL); lpw是你传入的TCHAR* or wchar_t, lpa是你最终的转换数组,
当然这个东东开始的内容需要自己分配,当然如果nChars这个是0的话,其实这个函数只是数了下宽字符的个数,然后将这个个数当做返回值返回,如果nChars这个
不为零,那么就是要填充的大小了,并且这个函数真正做了将宽字符转换成bytes的工作。CP_ACP这个是ascii页表。后两个产生对于未知的编码很有用,最后一
个你可以传入一个bool型的指针,如果所有的宽字符没有对应的多个窄字符,那么就会被倒数第二个参数替代,如果第二参数是NULL,那么就会使用?替代。当然此时这
个bool型指针的值就会变为true.

这样就可以各种类型的转换了。首先所有的类型转换为CString, 然后再用CString转为各种类型。

In Postgresql, If you want to do something like "select Hello(a) from A;". You should define your own function Hello().

First, go to postgresql root directory and go into contrib file folder. Create your own directory, and add hello.h , hello.c, Makefile, hello.sql.in and uninstall_Hello.sql.in

Makefile is like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
MODULE_big  = Hello // this is module name
OBJS = Hello.o // those will be create by execute "make"

DATA_built = hello.sql // install your function using this sql file
DATA = uninstall_Hello.sql
SHLIB_LINK = $(BE_DLLLIBS)

ifdef USE_PGXS // this is a build infrastructure of extentions in postgreSQL
PGXS = $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/Hello // here is your code files
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

// the following code fragment is copying content of *.sql.in into *.sql
%.sql: %.source
rm -f $@; \
C=`pwd`; \
sed -e "s:_OBJWD_:$$C:g" &lt; $&lt; &gt; $@

Attention!!! In Makefile those command should be with no blank at end.
Here we can write hello.sql.in:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
SET search_path = public; --you should add this code first.
--functions
--take care of those functions, if those functions are used for data input and out, their args or return type must be cstring or varchar

-- arg type is cstring
CREATE OR REPLACE FUNCTION hello_in(cstring)
RETURNS HelloS
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- return type is cstring
CREATE OR REPLACE FUNCTION hello_out(HelloS)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;

--data type
CREATE TYPE HelloS (
internallength = 52,
input = hello_in,
output = hello_out,
alignment = double
);
--size is 52 bytes and alignment is 8 bytes.
--if you don't know its real size, use internallength = VARIABLE
--if you want use binary array as its input and out, you should use receive=XXX_function, and send = XXX_function

--outer function
--this function can use kinds of types
CREATE OR REPLACE FUNCTION Hello(HelloS)
RETURNS cstring
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;

Here is the uninstall_Hello.sql.in:

1
2
3
4
5
6
SET search_path = public;

DROP FUNCTION hello_in(cstring);
DROP FUNCTION hello_out(HelloS);
DROP TYPE HelloS;
DROP FUNCTION Hello(HelloS);

In hello.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef HELLO_H
#define HELLO_H
#include&lt;stdio.h&gt;
#include&lt;stdlib.h&gt;

#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
// you should take care of the order of those head files!!!

typedef struct{
char content[52];
}HelloS;

Datum hello_in(PG_FUNCTION_ARGS);
Datum hello_out(PG_FUNCTION_ARGS);
Datum Hello(PG_FUNCTION_ARGS);

#endif

hello.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include “hello.h”

#ifndef MOD_FOR_PG
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(hello_in);
Datum
hello_in(PG_FUNCTION_ARGS)
{
// get args[0]
char * str = PG_GETARG_CSTRING(0);
HelloS * hs = palloc(sizeof(HelloS));
if(NULL != str){
strcpy(hs-&gt;content,str);
PG_RETURN_POINTER(hs)
}
PG_RETURN_NULL();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
PG_FUNCTION_INFO_V1(hello_out);
Datum
hello_out(PG_FUNCTION_ARGS)
{
// get args[0]
Hello * hs = PG_GETARG_POINTER(0);

if(NULL != hs){
char * content = palloc(sizeof(HelloS));
strcpy(content,hs-&gt;content);
PG_RETURN_CSTRING(content);
}
PG_RETURN_CSTRING("");
}

PG_FUNCTION_INFO_V1(Hello);
Datum
Hello(PG_FUNCTION_ARGS)
{
HelloS* hs = PG_GETARG_POINTER(0);
if(NULL != hs){
char * res = palloc(sizeof(HelloS));
sprintf(res,"hello %s",hs-&gt;content);
PG_RETURN_CSTRING(res);
}
PG_RETURN_CSTRING("hello nobody");
}

Then cd your folder contrib/Hello, make, and make install

Then start psql to execute :

create table A(a HelloS);

insert into A values(‘cc’);

insert into A values(‘ff’);

select Hello(a) from A;

result:

Hello cc

Hello ff

select * from A;

result:

cc

ff

Today I have found this problem :
1
2
3
error LNK2019: unresolved external symbol __imp__gethostname@8 referenced in function _wmain
and fatal error LNK1120: 1 unresolved externals

code fragment is :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
const int len = 256;
char buffer[len];
int a = gethostname(buffer,len);
cout &lt;&lt;a&lt;&lt;endl; // a will be -1
cout &lt;&lt; buffer&lt;&lt;endl; // buffer will be filled with unreadable code.
return 0;
}

What's wrong?

If you don't add #include <WinSock2.h>, the compiler will report :  error C3861: 'gethostname': identifier not found . But after you adding this header, it will report above error again.  First, you should add the header <afxext.h> into stdafx.h, then compile the code again. Code will be compiled without any error. Then run this code fragment, and the result is not my expected. a is -1, and the buffer is filled with messy code. If you use WSAGetLastError() function to see it error code, the error code will be WSANOTINITIALISED. Yes, I have not initialized. So we should call WSAStartup() first and then gethostname. And WSAStartup() will check DLL version. And after having gotten hostname, don't forget to call WSACleanup(). Here is the whole code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

#include "stdafx.h"
//#include &lt;winsock.h&gt;
#include <iostream>
#include <WinSock2.h> // use winsock2.h is ok
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
const int len = 256;
char buffer[len];
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2,2); //version 2.2
int err = WSAStartup(wVersionRequested,&amp;wsaData);
if (0 != err) return 1;
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
// only support version 2.2 of Windows Sockets
WSACleanup();
return 1;
}
// get hostname
int a = gethostname(buffer,len);
/* if there is an error. use WSAGetLastError to find it.
int errcode = WSAGetLastError();
switch(errcode){
....
}*/
cout << buffer << endl;
WSACleanup();
return 0;
}


在linux下如果不考虑断电系统重启等其他原因可以使用ftruncate()函数,这个函数输入参数为file descriptor 和 offset,
这个函数在unistd.h中,windows一般是用不了这个的。

另外使用文件名得到文件描述符的方法就是int fileno(FILE*); 注意之后别忘了fclose(),下面的代码里忘记写了。

#include #include #include<unistd.h> using namespace std;
int main(){ FILE* f = fopen(“abc.txt”,“w”); int fd = fileno(f); long long
offset = 102410241024*(long long)2; ftruncate(fd,offset); return 0; }

在windows及其他平台可以使用fseeko(FILE* , offset, pos)这个方法

#include #include using namespace std; int main(){ FILE* f =
fopen(“abc.txt”,“w”); long long offset=102410241024*(long long)2;
fseeko(f,offset,SEEK_SET); int i = 10; // write i to file end
fwrite(&i,sizeof(int),1,f); fclose(f); return 0; }

这样就可以快速得到2G的文件了。另外编译时不要忘记添加编译参数 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64

想看大文件测试的结果到 http://blog.csdn.net/cctt_1/archive/2010/05/23/5618652.aspx

the macro #define is the biggest hidden bug in c. You should always remember macro-function is like code paster. And it will slow down your system in some special situations, such as macro recursion. If you macro define some function use BIG characters.
1
2
3
4
5
6
7
8
9
10
11
12
#define FUN1(a,b) a*b
#define FUN2(a) a++;\
a*=a;

int main(){
int a = 2;
int b = 3;
FUN1(a,5+1); // =&gt; 2*5+1
if(a&gt;2)FUN2(a); //=&gt; if(a&gt;2) a++;a*=a;

return 0;
}

strcpy() will copy “\0”, and it is dangerous when you copy two points.

1
2
3
4
5
6
7
8
int main(){
char str1[] = "abcd";
char str2[] = "12";
strcpy(str1,str2); // ok, str1 equals "12"
char *st1 = "abcd";
char *st2 = "12";
strcpy(st1,st2); //crash!! st1 points to static const string
}

param as point or array style. Although they are differnt styles, they are the same.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int size1(char a[]){
cout &lt;&lt; sizeof(a);
}
int size2(char* a){
cout &lt;&lt; sizeof(a);
}
int main(){
char a[] = "abcdef";
char *b = "abcdef";
size1(a); // =&gt; sizeof(char*)
size1(b); // =&gt; sizeof(char*)
size2(a); // =&gt; sizeof(char*)
size2(b);// =&gt; sizeof(char*)
cout &lt;&lt; sizeof(a)&lt;&lt;endl; // =&gt;strlen(a)+1
cout &lt;&lt; sizeof(b)&lt;&lt;endl; // sizeof(char*)

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// There are 5 segments in codes, DATA, BSS, TEXT, heap, stack
// DATA stores all globel variables, and those variables are defined.
// BSS stores all globel variables, but those variables are not defined.
// const variables are in TEXT, and codes are in this segment also.
// heap store (malloc, calloc,realloc, new) data
// stack store function params, local variables.

int a; // a is in BSS
int b = 3; // b is in DATA
int fun(int c){ // c is in stack, when the function is called.
return 0;
}
int main(){
const int c = 4; // c is in TEXT
a = 4; // move to DATA
int x = 4; // in stack
int * p = malloc(sizeof(int)); // *p is in heap. but p is in stack.
return 0;
}

相信几乎每个人都遇到过memory leak的问题。解决方法各不相同。

1。防止内存泄露

例如c中使用auto_ptr, java中自己的垃圾回收。对于纯java, python的语言编写的东西,memory
leak一般不是啥米的问题,这些语言最严重的问题是内存不足。这些java要处理内存不足就-Xmx1024m或者开更大的内存,或者闲得无聊的时候调调gc.
python的解决方法差不多,不过它可以显式delete. 另外听说python调用django时会有内存分配不足的问题,原因在于django这鬼东西在de
bug==true时没有对sql查询进行释放。下面接着过去的话题扯下c
/c这些需要自己care的语言。
c++中有auto_ptr这东东算是可以,因为遵循RAII(resource acquirement is initial 不知道自己英文拼对了没有), 也
就是说:在类初始化的时候申请资源,在类析构的时候释放资源。另外注意析构函数是virtual的。为啥米呢?因为要多态调用析构父类。如果自己写的类不是那么标准,
喜欢到处申请资源,到处释放资源,还是建议使用auto_ptr这个类,它在中。其实auto_ptr类似于下面的代码:

template class simple_auto_ptr{ private: T* point; public: explicit
simple_auto_ptr(T* point):point(point){} virtual ~simple_auto_ptr(){delete
point;} }; 调用代码例如simple_auto_ptr a(new int(3));

这东东的作用在于简化下面的代码:

void foo(){ T* a = new T(); try{ throw something; }catch(something){
if(NULL!=a){ delete a; a=NULL; } } if(NULL != a) delete a; } 使用auto_ptr
将上面的简化为 void foo(){ auto_ptr a(new T()); throw something; }

可以说还是有些用处的…不过不能用于申请数组…除非你想申请auto_ptr的数组。另外传说不能用于容器类。所以为了不让内存泄露,还是需要谨慎小心。

2。监测内存泄露,使用监测内存泄露的小工具

另外有一些监测工具可以帮你检查一部分内存泄露的问题。有些工具其实就是替换了free/malloc/realloc/calloc 或者是
new/delete.采用宏定义就可以轻松做到:

#define new MY_NEW #define MY_NEW my_new

然后就可以截获new/delete的函数调用,至于你想再多做一些事情,就看你宏定义和你函数的具体写法了。然后就如同左右括号匹配一样。当然往往不是那么简单,例
如类中的一些指针有还有一些内存检测是需要你传入指针进去,然后catch指针做些监测工作。

但有些memory leak的问题很难被监测到,或者有时候会被误报。比如某个指针在函数中申请空间并传出,然后在外面进行n次转换,并进行加加见见运算,最后变为
另外一个指针。除非检测工具做了名字的转换,可以进行数学运算,比如int * a = new int[20]; int * c = ++a; delete
[] --c;当然这里只是一个模拟,没有人会这样写代码。但是真正的程序中很有可能代码简化后就是这样的情况。当然进行dynamic_cast的情况更加复杂,还
需要判断析构函数是否是虚函数等问题。

3。断言法

测试程序正确性很难监测出内存泄露的情况。

下面以链表为例:list_insert()时原List比现List少1个元素,list_delete()时,原List比现List多一个元素。

List * l = new List(); size_t old = l->size(); l->list_insert(some elements);
size_t new = l->size(); assert(new-old == 1); old = l->size();
l->list_delete(some elements); new = l->size(); assert(old-new == 1); //
另外必须保证list的size其实和具体的值无关,应该是遍历后的结果

即使这里的size变化是正确的,这也依旧不能保证list_delete()中调用了合适的delete 方法,有可能没有进行delete, 或者进行了节点的d
elete,但是组成链表中的节点的析构函数没有写好,也会造成内存泄露。个人就遇到PG中删除链表函数的问题。原链表长度的确是减小了。但是链表节点的内存的确没有
释放。

4。模拟法

这个方法其实很好用,一般在已经确定可能是某一个大模块的问题,但是不清楚内部可能的路径,也有可能是路径太过复杂。这里就可以模拟一下。化简各种流程,仅仅调用申请
释放资源的几个主要函数。然后逐一排除各个主要函数的可能性。例如那个链表,如果起初的业务流程有许多复杂的链表操作,但是申请释放空间的地方其实就是list_in
sert()和list_delete(),这就可以仅仅是调用几千次list_new(),list_delete()看看情况.内存泄露就会明显显现。

http://linux.vbird.org/linux_basic/0440processcontrol.php

top: failed tty get 错误, 因为top中没有加上-b选项。

free是监视内存的 used, free, swap等东东。

vmstat  是监视硬盘使用情况的。io情况的.包括memory, swap, io,system,cpu等

netstat 监视网络使用情况的,包括socket和协议等,以及传输的字节和接受的字节以及套接字类型stream/DGRAM/RAW

ps aux监视进程用的,一般可以看出占用cpu,memory的百分比和进程的优先级

ps -l 也是监视进程用的,一般看的是此bash下的进程使用cpu和内存的情况

top 这个很有用,用于监视某个进程。包括IO,cpu,内存等。其中的wa很有用,是wait event或者IO的百分比。id是cpu idle的情况。

基本上脚本监视也就用到这几个常用东西了…

0%