首页 新闻 会员 周边

请各位C++大神来看看这段小程序有没有潜在的BUG

1
悬赏园豆:5 [待解决问题]
 1 #include <iostream>
 2 #include <vector>
 3 #include <string.h>
 4 
 5 using namespace std;
 6 
 7 struct A{
 8     int a;
 9     char b[88];
10     char c[88];
11 };
12 
13 typedef enum {
14     TYPE_INT = 1,
15     TYPE_VARCHAR2 = 2,
16     TYPE_DATE
17 }ORA_DATATYPE_E;
18 
19 typedef struct {
20     ORA_DATATYPE_E type;
21     void * addr;
22 }ORA_ABSTRACT_DATA_T;
23 
24 void func(const vector<ORA_ABSTRACT_DATA_T> & vec) {
25     for (int i = 0; i < (int)vec.size(); i++) {
26         if (vec[i].type == TYPE_INT) {
27             std::cout << "int : " << *((int *)vec[i].addr) << std::endl;
28         } else if (vec[i].type == TYPE_VARCHAR2) {
29             std::cout << "varchar2 : " << (char *)vec[i].addr << std::endl;
30         }
31     }
32 }
33 
34 int main(void) {
35 
36     struct A a;
37 
38     memset(&a, 0, sizeof(a));
39 
40     a.a = 4;
41     memcpy(a.b, "abcd", strlen("abcd"));
42     memcpy(a.c, "efgh", strlen("efgh"));
43 
44     vector<ORA_ABSTRACT_DATA_T> vec;
45     ORA_ABSTRACT_DATA_T data;
46 
47     data.type = TYPE_INT;
48     data.addr = (void *) new int;
49     memcpy(data.addr, &a.a, sizeof(a.a));
50     vec.push_back(data);
51 
52     data.type = TYPE_VARCHAR2;
53     data.addr = (void *) new char[strlen(a.b)];
54     memcpy(data.addr, a.b, strlen(a.b));
55     vec.push_back(data);
56 
57     data.type = TYPE_VARCHAR2;
58     data.addr = (void *) new char[strlen(a.c)];
59     memcpy(data.addr, a.c, strlen(a.c));
60     vec.push_back(data);
61 
62     func(vec);
63 
64     for (int i = 0; i < (int)vec.size(); i++) {
65         if (vec[i].type == TYPE_INT) {
66             if (vec[i].addr) {
67                 delete (int *)vec[i].addr;
68                 vec[i].addr = NULL;
69             }
70         } else if (vec[i].type == TYPE_VARCHAR2) {
71             if (vec[i].addr) {
72                 delete (char *)vec[i].addr;
73                 vec[i].addr = NULL;
74             }
75         }
76     }
77 
78     vec.clear();
79 
80 }

我想用这种方式,将一个大型结构体中的数据存放到vector中,这样就可以在get数据库SQL插入语句时,使用for循环来bind参数,不用把结构体中的变量一一列举出来了。

现在这样写,在本机运行是正常的,但理论上是不是存在什么风险呢?

豪放婉约派程序员的主页 豪放婉约派程序员 | 初学一级 | 园豆:197
提问于:2016-03-18 16:46
< >
分享
所有回答(5)
0

小弟看了一下,个人觉得,就这个程序感觉很棒。在我的理解范围内,应该没有。结构体中,使用指针,要防止浅拷贝。使用了数组,防止越界。嘿嘿,就知道这么多了。如有不对,还请指正。

[0] | 园豆:1257 (小虾三级) | 2016-03-20 20:34

其实

data.addr = (void *) new char[strlen(a.b)];

应该改成

data.addr = (void *) new char[strlen(a.b) +1];

来保证存在一位结束符

支持(0) 反对(0) 豪放婉约派程序员 | 园豆:197 (初学一级) | 2016-03-21 09:06

@豪放婉约派程序员: AIYA,越简单越容易忽略。

支持(0) 反对(0) [0] | 园豆:1257 (小虾三级) | 2016-03-21 14:59
0

~~(╯﹏╰)b 除了教材,还从来没遇到过这种代码。   代码一般看看不粗来,最好是运行一下。

小刺猬001 | 园豆:660 (小虾三级) | 2016-03-29 16:09
0

这样做没什么必要, 参数拷贝一份, 无谓的开销. 

cn.stonexy | 园豆:312 (菜鸟二级) | 2016-04-20 17:46
0

你的思路可以尝试(但是需要扩展很多类型), 但是你代码语法存在问题. 你好像写的不是C++, 是 "乱炖".

1. string.h 是什么鬼, 不都是 cstring?

2. 88是什么鬼(A, a, b, c 也可以忍受) , 魔法数字是万恶之源

3. typedef enum { ... } xxx 是什么鬼, 那是c 不是C++ , 不需要 typedef .. 推荐学习深入了解 纯粹的 C++

4. (int)vec.size() 是什么鬼, 编译器知道 二者怎么比较, 不需要强转 , 最终以大类型为主比较的

5. struct A a; 这是什么鬼, C++ 不是 c, A a;就可以了

6. memset 0 了, 每次都这么写直接放在 A 结构体的构造函数中就可以了. C++ 类和结构推荐用构造函数初始化

6. (int *)vec[i].addr 不地道, C++ 推荐 static_cast

7. std::cout 和 using namespace std; 是画蛇添足, 推荐删掉 using 声明空间.

8. strlen("abcd") 是可以记着, 没必要每次都是 来一遍求长度 , O(n) 级别的浪费

9.  后面 delete , 对于你那个 int char * 完全可以, 后面可以优化 .

  直接 delete vec[i].addr; 销毁, 因为没有特殊的析构需要执行

10. 你是 int mian ... 然而 return 0; 或者 exit(EXIT_SUCCESS); 呢, 又消失了~~~

 

上面就是你的问题, 更加合适的可以看 boost::any  C++ 结构.

最后补充一条, 你要是说你是 C + STL 我也算了, 来个 strlen("xxxx") , C字符串隐藏BUG之源呀. 

要多看教程, 多做题呀.....

喜欢兰花山丘 | 园豆:222 (菜鸟二级) | 2016-11-06 23:04

别人这样写可以啊。。你这纯粹是瞎找错。。这是BUG吗??并且你写的mian是什么玩意。。

支持(0) 反对(0) Aehnuwx | 园豆:263 (菜鸟二级) | 2018-07-14 13:54

@蛤?蛤!: 那时候年轻, 工作用C++, 现在应该都不会了. 多见谅

支持(0) 反对(0) 喜欢兰花山丘 | 园豆:222 (菜鸟二级) | 2018-07-17 15:29

@喜欢兰花山丘: emmm

支持(0) 反对(0) Aehnuwx | 园豆:263 (菜鸟二级) | 2018-07-17 15:30
0

我个人感觉应该没有什么bug了。

Aehnuwx | 园豆:263 (菜鸟二级) | 2018-07-14 13:56
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册