繁体   English   中英

C ++ char数组-相同的输入提供不同的输出

[英]C++ char arrays - same input giving different outputs

我有一个cpp类,该类实现了Netezza用户定义的函数( 在此处提供文档)。 它接受一个将是某种日期格式的字符串的参数,并将其转换为YYYYMMDD格式。 如果不是有效日期,它将返回“ 99991231”。 每当我在某些表上运行代码时,对于相同的输入,每次都会得到不同的输出。 我假设存在一些我没有看到的内存问题。

从逻辑上讲,我们将char数组retval设置为等于date命令的输出。 如果输出为空,则设置为“ 99991231”。 然后,我们将temp char数组设置为retval的前9个字节(最后一个为空终止符)。 然后,我们将其存入ret-> data(必须返回的结构的char ptr)。

#include <stdarg.h>
#include <string.h>
#include "udxinc.h"
#include "udxhelpers.h"

using namespace nz::udx_ver2;

class Dateconvert: public Udf
{
public:

    Dateconvert(UdxInit *pInit) : Udf(pInit){}
    ~Dateconvert(){}

    static Udf* instantiate(UdxInit *pInit);

    virtual ReturnValue evaluate()
    {

      StringReturn* ret = stringReturnInfo();
      StringArg *str;
      str = stringArg(0);

      int lengths = str->length;
      char *datas = str->data;

      string tempData = datas;

      string shell_arg = tempData;
      shell_arg = "'" + shell_arg + "'";
      string cmd="date -d " + shell_arg +  " +%Y%m%d 2>/dev/null";

      FILE *ls = popen(cmd.c_str(), "r");
      char retval[100];
      retval[0]='n';
      fgets(retval, sizeof(retval), ls);

      if(!isdigit(retval[0]))
      {
          strcpy(retval,"99991231");
      }

      pclose(ls);

      char temp1[9];
      memcpy(temp1, retval, 8);
      temp1[8]='\0';

      ret->size = 9;
      memcpy(ret->data, temp1, 9);

      NZ_UDX_RETURN_STRING(ret);
    }
};


Udf* Dateconvert::instantiate(UdxInit *pInit)
{
    return new Dateconvert(pInit);
}

当我在Netezza中的一个不同值上运行UDF时,它给了我预期的输出。 但是,当我在多列上运行它时,输出有时是正确的,有时是错误的,看似随机的。 我认为这必须是内部存储器问题。 例子:

   input          output
1) 8/11/2014      20140811

2) 8/11/2014      20140811
   Fri 10/17/14   20141017

3) 8/11/2014      99991231
   Fri 10/17/14   20141017

4) 8/11/2014      20140811
   Fri 10/17/14   20141017

5) 8/11/2014      20140811
   Fri 10/17/14   20141017
   9-Nov-12       20121109

6) 8/11/2014      20140811
   Fri 10/17/14   20141017
   9-Nov-12       01241109 (what?)

7) 8/11/2014      99991231
   Fri 10/17/14   20141017
   9-Nov-12       20121109

只要调用该函数一次,它就会返回正确的答案。 多次调用时会出现问题,我不理解。 为什么会有什么遗留? 在评估函数末尾将返回值大小从9更改为8并不能解决问题。

这是调用函数的格式:

select a.val1, DATECONVERT(a.val1)
from
(
 select '8/11/2014' as val1 from calendar
 union
 select 'Fri 10/17/14' as val1 from calendar
 union
 select '9-Nov-12' as val1 from calendar
) a

并为UDF编译命令:

nzudxcompile /export/home/nz/dateconvert.cpp -o dateconvert.o --sig "Dateconvert(VARCHAR(200))" --version 2 --return "VARCHAR(200)" --class Dateconvert --user user1 --pw mypw  --db mydb

顺理成章,这里的问题是如何分配tempData。

  StringReturn* ret = stringReturnInfo();
  StringArg *str;
  str = stringArg(0);

  int lengths = str->length;
  char *datas = str->data;

  string tempData = datas;

StringArg不存储NUL终止的字符串,而是提供长度,并希望您自己进行管理。

select a.val1, ADMIN.DATECONVERT(a.val1)
from
(
 select '09-Nov-12'::varchar(20) as val1 
 union all
 select '9-Nov-12'::varchar(20) as val1 
) a;

   VAL1    | DATECONVERT 
-----------+-------------
 09-Nov-12 | 20121109
 9-Nov-12  | 01221109
(2 rows)

在此示例中,正在发生的事情是,当将第二个较短的字符串分配给tempData时,较长的第一个字符串在内存中仍然有一个字符徘徊。 末尾悬挂的“ 2”像这样添加:

09-Nov-12
9-Nov-122

这些都是迄今为止有效的输入,可以很好地解释您所看到的输出。

$ date -d 09-Nov-12 +%Y%m%d
20121109
$ date -d 09-Nov-122 +%Y%m%d
01221109 

更改分配以使用该长度,就可以避免此问题。

  //string tempData = datas;
  string tempData(datas, datas+lengths);

然后,您将获得预期的输出:

select a.val1, ADMIN.DATECONVERT(a.val1)
from
(
 select '09-Nov-12'::varchar(20) as val1 
 union all
 select '9-Nov-12'::varchar(20) as val1 
) a;

   VAL1    | DATECONVERT 
-----------+-------------
 09-Nov-12 | 20121109
 9-Nov-12  | 20121109
(2 rows)

话虽如此,我不知道您在此UDF中采用的整体方法是否行得通。 当我在上面运行它时,这些行是在主机上生成的,因为它们在SQL中进行了硬编码,并且日期肯定在主机上可用。 但是,您不能指望在MPP后端(我们通常称为SPU)上运行的代码具有与主机上相同的linux实用程序可用性,或者如果它们存在,它们具有相同的功能。

如果我将日期移到实际表中,则UDF将在SPU上对其进行操作,并且会给我不好的输出,因为SPU映像上的date命令与主机的显着不同,并且对此不理解输入格式。

select a.col1, admin.DATECONVERT(a.col1) from calendar a;

   COL1    | DATECONVERT 
-----------+-------------
 09-Nov-12 | 99991231
 9-Nov-12  | 99991231
(2 rows)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM