








Linux下用g++编译共享库的一个问题
最近在使用linux下的共享库so的时候遇到一个奇怪的问题,做个记录,方便备查。
一般来说,如果用gcc编译的时候加上-shared和-fPIC选项,可以把源文件编译成一个so文件,可以在其他源程序连接阶段把这个链接上去,从而可以调用so文件提供的函数接口,这样可以多文件共用一个so文件提供的函数,即节省内存空间,也便于更新,所有的接口只需要更新so文件就行。
其实除了上面的方法,还有一个方法,那就是在运行时由程序自己动态加载so文件,使用一系列系统调用如dlopen,dlsym,dlclose等来进行动态加载,获取函数地址从而进行函数调用,关闭加载的so文件等。
一般以第一种方法用得多,但是第二种方法更灵活,结合配置文件,更具一般意义上的服务扩展性。 但是就是在用第二种方法的时候出现了一点问题。
这里把问题抽象一下,假设有一个源文件是要编译为so文件的,假设这个源文件只提供一个简单的函数,add,取两个整数为参数,返回它们的和,源文件为add.c,代码如下:
1 2 3 4 5 6 | #include <stdio.h> int add( int a, int b) { return a+b; } |
gcc -shared -fPIC add.c -o libadd.so
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 | #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main( int argc, char *argv[]) { void * handle; int (*func)( int , int ); char *error; handle = dlopen( "libadd.so" , RTLD_LAZY); if (!handle) { fprintf (stderr, "%s\n" , dlerror()); exit (1); } func = ( int (*)( int , int ))dlsym(handle, "add" ); if ((error = dlerror()) != NULL) { fprintf (stderr, "%s\n" , error); exit (1); } func(3, 4); dlclose(handle); return 0; } |
gcc test.c -o test -ldl
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
./libadd.so: undefined symbol: add
$ nm libadd.so |grep add
00000000000005ec T _Z3addii
$ c++filt _Z3addii
add(int, int)
1 2 3 4 | extern "C" { // the function code ... } |
$ nm libadd.so |grep add
00000000000005dc T add
15身份证号码转18位的程序
以前在哪看到的,安全焦点吧!丢这做个备份
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | /*输入原来的15位身份证号码,产生新的18位身份证号码的程序*/ #include "stdio.h" #include "string.h" #include "conio.h" /* * gen New 18 ID Card from old 15 ID */ char genNewID( char ID[], char NewID[]) { int W[18] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1}; char A[11] = { '1' , '0' , 'x' , '9' , '8' , '7' , '6' , '5' , '4' , '3' , '2' }; int i,j,S; if ( strlen (ID) != 15) return -1; memcpy ( NewID, ID, 6 ); NewID[6]= '1' ; NewID[7]= '9' ; NewID[8]=0; strcat ( NewID, &ID[6] ); S = 0; for (i=0;i<17;i++) { j = (NewID[i] - '0' ) * W[i]; S = S + j; } S = S % 11; NewID[17] = A[S]; NewID[18] = 0; return A[S]; } int main( int argc, char * argv[]) { char ID[20], NewID[20], ret; puts ( "输入原来的15位身份证号码,产生新的18位身份证号码\n" ); do { printf ( "Input your old 15 ID Card: " ); scanf ( "%s" , ID ); if (stricmp(ID, "exit" ) == 0) break ; ret = genNewID( ID, NewID ); printf ( "Your New 18 ID Card: %s \n" , ret != -1 ? NewID : "Input Error!!" ); } while (1); getch(); return 0; } |
测试堆的最大申请数量
看到说linux下的虚拟地址空间分给进程本身的是3GB(高址的1GB是内核空间,也就是0xc000000以上地址),所以有这样一个程序来测试用malloc最多能申请多少内存?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include<stdio.h> #include unsigned max=0; int main( void ) { int i,count; unsigned size[]={1024*1024,1024,1}; for (i=0;i<3;i++){ for (count=1;;count++){ void *p= malloc (max+count*size[i]); if (p){ max+=count*size[i]; free (p); } else { break ; } } } printf ( "The max memory i can alloc is %u\n" ,max); return 0; } |
在我的linux机器上跑了后发现只有1.1G左右的空间,想一下应该是内存768M+swap400多M,所以到不了那么大吧!
求三个参数中最大两个的平方和
看到一题,实现一个函数,求三个函数中最大的两个参数的平方和。
很自然的,想到这样的方法:
if(y > x && z > x){
return y * y + z * z;
}
if(x > y && z > y){
return x * x + z * z;
}
if(x > z && y > z){
return x * x + y * y;
}
}
if (x <= y && x <= z){
return y * y + z * z;
}
return sum_square_largest(y, z, x);
}
分享代码的好地方
介绍一个分享以及在线运行代码的好地方,codepad,在线运行支持语言种类也很多,当然那个PlainText就免谈了(其实是分享用)。
Language:
界面很简洁,一看就知道怎么用,注意到下面那个Private选项了吗?这里其实可以分享代码,是个geek的好地方,有的人甚至写出了VIM上 用的插件,可以直接在vim里面写代码,然后发布到这里来分享。
程序员用的东西一向以简洁高效著称,这里的注册就很简单,只要你打个用户名和密码就成,密码也让你只打一遍,请保证正确,不过geek一般都自信不会打错。
想看最近都有哪些代码提交,点击那个Recent Pastes就可以看到一大串的列表了,还有提交时间。