免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3897 | 回复: 5
打印 上一主题 下一主题

[ESQL游标]用字符串指针作为where后的匹配项导致数据丢失问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-31 17:04 |只看该作者 |倒序浏览
本帖最后由 dreamtang 于 2010-07-31 17:51 编辑

代码在SCO unix上,网络没设置好,不能telnet进去。程序所操作的数据库是INFORMIX_SE。

代码大概的逻辑下面应该能说清楚:

void get_str(char *myid, char *mypwd, int *mytype, char *myname)
{
    EXEC SQL BEGIN DECLARE SECTION ;
        char *getid = NULL ;
        char *getpwd = NULL ;
        int *gettype = NULL ;
        char *getname = NULL ;
    EXEC SQL END DECLARE SECTION ;

    getid = myid ;
    getpwd = mypwd ;
    gettype = mytype ;
    getname = myname ;

    EXEC SQL DECLARE get_info cursor for
        select pwd, type, name
            into $getpwd, $*gettype, $getname
        from operaform
        where id = $getid ;

     EXEC SQL OPEN get_info ;

     EXEC SQL FETCH get_info ;//问题出在这里,当FETCH完之后,“getid”里原有的数据就没了。

     EXEC SQL close get_info ;
     EXEC SQL free get_info ;
}

int main()
{
    char id[20] = "s001" ;
    char password[20] ;
    int type = 0 ;
    char name[20] = "unknowed" ;

    EXEC SQL BEGIN DECLARE SECTION ;
        char path[] = "/usr/student/informix_database/operaform" ;
    EXEC SQL END DECLARE SECTION ;

    EXEC SQL DATABASE $path ;
    get_str(id, password, &type, name) ;--执行完成后,printf("%s\n", id) 输出基本也是空的,而不是输出"s001"
    EXEC SQL CLOSE DATABASE ;
    return (0) ;
}


--请问这是什么问题?

--还有,为什么在定义游标的时候,在into后不能使用“:myid”来使用c语言变量?我希望可以在游标里直接把数据存储到函数形参表里的形参中。

--最后,时间紧迫~~DX帮帮忙~

论坛徽章:
0
2 [报告]
发表于 2010-07-31 17:26 |只看该作者
本帖最后由 dreamtang 于 2010-07-31 17:28 编辑

刚telnet进去把源文件拷贝出来,帖一下代码:

EXEC SQL INCLUDE sqlca.h ;
#include <stdio.h>
#include <string.h>

void get_str_out(char *myid, char *mypwd, int *mytype, char *myname)
{
        EXEC SQL BEGIN DECLARE SECTION ;
                char *temp_id = NULL ;
                char *getid = NULL ;
                char *getpwd = NULL ;
                int *gettype = NULL ;
                char *getname = NULL ;
        EXEC SQL END DECLARE SECTION ;

        //strcpy(temp_id, myid) ;
        getid = myid ;
        getpwd = mypwd ;
        gettype = mytype ;
        getname = myname ;

        printf("myid = %s, getid = %s, myidAdd=%d, getidAdd=%d\n", myid, getid, myid, getid) ;

        EXEC SQL DECLARE get_str cursor for
                select pwd, type, name
                        into $getpwd, $*gettype, $getname
                from operaform
                where id = $getid ;

        printf("1getid = %s.\n", getid) ; //输出“3getid = s001"
        EXEC SQL OPEN get_str ;
        printf("2getid = %s.\n", getid) ; //输出“3getid = s001"

        if (SQLCODE != 0)
        {
                printf("Failed to open cursor.\n") ;
                return ;
        }
        EXEC SQL FETCH get_str ;
        printf("3getid = %s.\n", getid) ; //输出“3getid =         .”
        if (SQLCODE == 0)
        {
                printf("ID = %s, pwd = %s, type = %d, name = %s\n", getid, getpwd, *gettype, getname) ;
                EXEC SQL CLOSE get_str ;
                printf("4getid = %s.\n", getid) ; //输出“3getid =         .”
                EXEC SQL FREE get_str ;
                printf("5getid = %s.\n", getid) ; //输出“3getid =         .”
                return ;
        }
        else if (SQLCODE == 100)
        {
                printf("No such user.\n") ;
                EXEC SQL CLOSE get_str ;
                EXEC SQL FREE get_str ;
                return ;
        }
        else
        {
                printf("Failed to fetch cursor.\n") ;
                EXEC SQL CLOSE get_str ;
                EXEC SQL FREE get_str ;
        }
        //strcpy(myid, temp_id) ;
        return ;
}

void main()
{
        char myid[20] = "s001" ;
        char mypwd[20] ;
        char myname[20] ;
        int mytype ;

        $char path[] = "/usr/linkang/informix_database/operaform" ;

        EXEC SQL DATABASE $path ;
        if (SQLCODE != 0)
        {
                printf("Failed to open database.\n") ;
                return ;
        }

        printf("1id = %d, pwd = %d,name=%d\n", myid, mypwd, myname) ;

        get_str_out(myid, mypwd, &mytype, myname) ;

        printf("1ID = %s, PWD = %s, TYPE = %d, NAME = %s\n", myid, mypwd, mytype, myname) ;
        EXEC SQL CLOSE DATABASE ;
        if (SQLCODE != 0)
        {
                printf("Failed to close database.\n") ;
                return ;
        }
        return ;
}

论坛徽章:
0
3 [报告]
发表于 2010-08-02 22:50 |只看该作者
我帮你修改下了,不过你的程序问题比较多。

EXEC SQL INCLUDE sqlca.h ;
#include <stdio.h>
#include <string.h>

void get_str_out(char *myid,char *mypwd,long *mytype,char *myname )
{
        EXEC SQL BEGIN DECLARE SECTION ;
                char temp_id = NULL ;
                char getid[20]   ;
                char getpwd[20]   ;
                long gettype   ;        
                char getname[20]   ;                        
        EXEC SQL END DECLARE SECTION ;

        //strcpy(temp_id, myid) ;

        strcpy(getid,myid);


        printf("myid = %s, getid = %s\n", myid, getid) ;

        EXEC SQL DECLARE get_str cursor for
                select pwd, type, name
                   /*     into $getpwd, $*gettype, $getname */
                        into :getpwd, :gettype, :getname
                from operaform
                where id = :getid ;

        printf("1getid = %s.\n", getid) ;
        EXEC SQL OPEN get_str ;
        printf("2getid = %s.\n", getid) ;

        if (SQLCODE)
        {
                printf("Failed to open cursor.\n") ;
                return ;
        }
        EXEC SQL FETCH get_str ;
        printf("3getid = %s %d.\n", getid,gettype) ;
        if (SQLCODE == 0)
        {
                printf("ID = %s, pwd = %s, type = %d, name = %s\n", getid, getpwd, gettype, getname) ;
                strcpy(mypwd,getpwd);
                *mytype = gettype;
                strcpy(myname,getname);
                EXEC SQL CLOSE get_str ;
                printf("4getid = %s.%d\n", getid,mytype) ;
                EXEC SQL FREE get_str ;
                printf("5getid = %s.\n", getid) ;
               
                                               return ;
        }
        else if (SQLCODE == 100)
        {
                printf("No such user.\n") ;
                EXEC SQL CLOSE get_str ;
                EXEC SQL FREE get_str ;
                return ;
        }
        else
        {
                printf("Failed to fetch cursor.\n") ;
                EXEC SQL CLOSE get_str ;
                EXEC SQL FREE get_str ;
        }
        //strcpy(myid, temp_id) ;
        return ;
}

void main()
{
        char myid[20] = "s001" ;
        char mypwd[20] ;
        char myname[20] ;
        long mytype ;

                                memset(mypwd,0x00,sizeof(mypwd));
                                memset(myname,0x00,sizeof(myname));
       /* $char path[] = "/usr/linkang/informix_database/operaform" ;  */

        EXEC SQL DATABASE test;
        if (SQLCODE != 0)
        {
                printf("Failed to open database.\n") ;
                return ;
        }

        printf("1id = %s, pwd = %s,name=%s\n", myid, mypwd, myname) ;

        get_str_out(myid,mypwd,&mytype,myname) ;

        printf("1ID = %s, PWD = %s, TYPE = %d, NAME = %s\n", myid, mypwd, mytype, myname) ;
        EXEC SQL CLOSE DATABASE ;
        if (SQLCODE != 0)
        {
                printf("Failed to close database.\n") ;
                return ;
        }
        return ;
}

论坛徽章:
0
4 [报告]
发表于 2010-08-03 10:55 |只看该作者
你在程序中的宿主变量都是指针,如果从数据库中取出的值长度大于指针指向的内存长度导致溢出。

论坛徽章:
0
5 [报告]
发表于 2010-08-05 09:33 |只看该作者
本帖最后由 dreamtang 于 2010-08-05 09:47 编辑

回复 3# sqlnet


    1.我对你程序的思考:我刚对比了一下修改前后两个源程序,我现在的认知是:你修改后,是将“get_str_out”里传入的字符串指针里的内容拷贝到“函数体里申明的变量char getid[20]”中进行操作。这样从安全的角度上避免了对指针的操作。

   
   2.我的想法是:我在main函数中,将主程序的“指针传入”--“get_str_out”函数中,因为函数里的指针“char *getid”指向的是“char id[ID_LEN + 1]”,而“ID_LEN + 1” 确保了从数据库获取的字符串长度不会造成id的溢出。这时候我直接操作“char *getid”,通过指针修改原先“char id[ID_LEN + 1]”里的内容。

                SORRY:刚才看了自己的main函数,发现定义的时候定义成“char id[20]”了。这样确实溢出了。不过在我最开始的源码里,我是定义成char id[ID_LEN + 1]这样的类型。而ID_LEN是数据库表中“id”字段的最大字符串长度。

   3.我想你的想法是对的,尽量避免了指针。不过我还是有疑惑,就是你有理解到我程序里希望通过对指针操作,直接修改“原调用函数里的字符串里内容”的意愿了?

论坛徽章:
0
6 [报告]
发表于 2010-08-05 09:36 |只看该作者
本帖最后由 dreamtang 于 2010-08-05 09:47 编辑

回复 4# happer_xc


    我定义结构体的时候是蛮小心的,结构体里的每个“数据字符串--如char id[ID_LEN + 1]”与数据库表中“id”字段相对应,而ID_LEN就是创建数据库时,类型为“char”的字段“id”的最大长度了。
   所以我觉得指针所指的可操作空间,应该是大于数据库取出数据的最大长度的。

               SORRY:刚才看了自己的main函数,发现定义的时候定义成“char id[20]”了。这样确实溢出了。不过在我最开始的源码里,我是定义成char id[ID_LEN + 1]这样的类型。而ID_LEN是数据库表中“id”字段的最大字符串长度。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP