C++ C代码-需要澄清有效性

C++ C代码-需要澄清有效性,c++,c,unix,gdb,dbx,C++,C,Unix,Gdb,Dbx,嗨,我已经写了一个基于需求的代码 (第1区第6区第2区第30区第3区第16区第4区第1区第6区第7区第2区第8区第1区)。。。。。 这是一个数据桶(8个字段)。我们一次将收到20个桶,即总共160个字段。 我需要根据预定义条件获取字段3、字段7和字段8的值。 如果输入参数为N,则从第一个桶中取出三个字段,如果为Y,则需要 从除第一个桶以外的任何其他桶中取出三个字段。 如果argumnet是Y,那么我需要逐个扫描所有20个bucket并进行检查 bucket的第一个字段不等于0,如果为true,则

嗨,我已经写了一个基于需求的代码

(第1区第6区第2区第30区第3区第16区第4区第1区第6区第7区第2区第8区第1区)。。。。。 这是一个数据桶(8个字段)。我们一次将收到20个桶,即总共160个字段。 我需要根据预定义条件获取字段3、字段7和字段8的值。 如果输入参数为N,则从第一个桶中取出三个字段,如果为Y,则需要 从除第一个桶以外的任何其他桶中取出三个字段。 如果argumnet是Y,那么我需要逐个扫描所有20个bucket并进行检查 bucket的第一个字段不等于0,如果为true,则获取该bucket的三个字段并退出。 我已经写了代码,它也工作得很好。但是我不太相信它是有效的。 我担心某个时候会崩溃。请建议下面是代码

int CMI9_auxc_parse_balance_info(char *i_balance_info,char  *i_use_balance_ind,char *o_balance,char *o_balance_change,char *o_balance_sign
)
{
  char *pch = NULL;
  char *balance_id[MAX_BUCKETS] = {NULL};
  char balance_info[BALANCE_INFO_FIELD_MAX_LENTH] = {0};
  char *str[160] = {NULL};
  int i=0,j=0,b_id=0,b_ind=0,bc_ind=0,bs_ind=0,rc;
  int total_bukets ;
  memset(balance_info,' ',BALANCE_INFO_FIELD_MAX_LENTH);
  memcpy(balance_info,i_balance_info,BALANCE_INFO_FIELD_MAX_LENTH);
  //balance_info[BALANCE_INFO_FIELD_MAX_LENTH]='\0';
  pch = strtok (balance_info,"*");
  while (pch != NULL && i < 160)
  {
     str[i]=(char*)malloc(strlen(pch) + 1);
     strcpy(str[i],pch);
     pch = strtok (NULL, "*");
     i++;
  }
total_bukets  = i/8  ;
  for (j=0;str[b_id]!=NULL,j<total_bukets;j++)
  {
  balance_id[j]=str[b_id];
  b_id=b_id+8;
  }
  if (!memcmp(i_use_balance_ind,"Y",1))
  {
     if (atoi(balance_id[0])==1)
     {
        memcpy(o_balance,str[2],16);
        memcpy(o_balance_change,str[3],16);
        memcpy(o_balance_sign,str[7],1);
        for(i=0;i<160;i++)
        free(str[i]);
        return 1;
     }
     else
     {
        for(i=0;i<160;i++)
        free(str[i]);
      return 0;
     }
  }
  else if (!memcmp(i_use_balance_ind,"N",1))
  {
      for (j=1;balance_id[j]!=NULL,j<MAX_BUCKETS;j++)
      {
        b_ind=(j*8)+2;
        bc_ind=(j*8)+3;
        bs_ind=(j*8)+7;
       if (atoi(balance_id[j])!=1 && atoi( str[bc_ind] )!=0)
       {
        memcpy(o_balance,str[b_ind],16);
        memcpy(o_balance_change,str[bc_ind],16);
        memcpy(o_balance_sign,str[bs_ind],1);
        for(i=0;i<160;i++)
        free(str[i]);
        return 1;
       }
      }
     for(i=0;i<160;i++)
     free(str[i]);
    return 0;
  }
 for(i=0;i<160;i++)
 free(str[i]);
return 0;
}
int CMI9_auxc_parse_balance_info(字符*i_balance_info,字符*i_use_balance_ind,字符*o_balance,字符*o_balance_change,字符*o_balance_sign
)
{
char*pch=NULL;
char*balance_id[MAX_bucket]={NULL};
字符余额信息[余额信息字段最大长度]={0};
char*str[160]={NULL};
int i=0,j=0,b_id=0,b_ind=0,bc_ind=0,bs_ind=0,rc;
国际总预算;
memset(余额信息),余额信息字段最大长度;
memcpy(余额信息、i余额信息、余额信息字段、最大长度);
//余额信息[余额信息字段最大长度]='\0';
pch=strtok(余额信息,“*”);
而(pch!=NULL&&i<160)
{
str[i]=(char*)malloc(strlen(pch)+1);
strcpy(str[i],pch);
pch=strtok(空,“*”);
i++;
}
总数=1/8;

对于(j=0;str[b_id]!=NULL,j我的感觉是这段代码非常脆弱。如果输入正确(我不建议为您进行桌面检查),它可能会很好地工作,但如果输入错误,它将崩溃并烧掉,或者给出误导性的结果

您是否测试过意外输入?例如:

  • 假设i\u balance\u info为空
  • 假设我的余额信息是“”
  • 假设输入字符串中的项少于8项,这行代码将做什么

    memcpy(o_balance_sign,str[7],1);
    
  • 假设str[3]中的项长度小于16个字符,那么这行代码将做什么

    memcpy(o_balance_change,str[3],16);
    

我编写此类代码的方法是防止所有此类事件的发生语句,我通常会编写显式输入验证,并在错误时返回错误。这里的问题是,接口似乎不允许出现错误输入的任何可能性。

我很难阅读您的代码,但FWIW我添加了一些注释,HTH:

// do shorter functions, long functions are harder to follow and make errors harder to spot
// document all your variables, at the very least your function parameters
// also what the function is suppose to do and what it expects as input
int CMI9_auxc_parse_balance_info
(
  char *i_balance_info,
  char *i_use_balance_ind,
  char *o_balance,
  char *o_balance_change,
  char *o_balance_sign
)
{
  char *balance_id[MAX_BUCKETS] = {NULL};
  char balance_info[BALANCE_INFO_FIELD_MAX_LENTH] = {0};
  char *str[160] = {NULL};
  int i=0,j=0,b_id=0,b_ind=0,bc_ind=0,bs_ind=0,rc;
  int total_bukets=0; // good practice to initialize all variables

  //
  // check for null pointers in your arguments, and do sanity checks for any
  // calculations
  // also move variable declarations to just before they are needed
  //

  memset(balance_info,' ',BALANCE_INFO_FIELD_MAX_LENTH);
  memcpy(balance_info,i_balance_info,BALANCE_INFO_FIELD_MAX_LENTH);
  //balance_info[BALANCE_INFO_FIELD_MAX_LENTH]='\0';  // should be BALANCE_INFO_FIELD_MAX_LENTH-1

  char *pch = strtok (balance_info,"*"); // this will potentially crash since no ending \0

  while (pch != NULL && i < 160)
  {
    str[i]=(char*)malloc(strlen(pch) + 1);
    strcpy(str[i],pch);
    pch = strtok (NULL, "*");
    i++;
  }
  total_bukets  = i/8  ;
  // you have declared char*str[160] check if enough b_id < 160
  // asserts are helpful if nothing else assert( b_id < 160 );
  for (j=0;str[b_id]!=NULL,j<total_bukets;j++)
  {
    balance_id[j]=str[b_id];
    b_id=b_id+8;
  }
  // don't use memcmp, if ('y'==i_use_balance_ind[0]) is better
  if (!memcmp(i_use_balance_ind,"Y",1))
  {
    // atoi needs balance_id str to end with \0 has it?
    if (atoi(balance_id[0])==1)
    {
      // length assumptions and memcpy when its only one byte
      memcpy(o_balance,str[2],16);
      memcpy(o_balance_change,str[3],16);
      memcpy(o_balance_sign,str[7],1);
      for(i=0;i<160;i++)
        free(str[i]);
      return 1;
    }
    else
    {
      for(i=0;i<160;i++)
        free(str[i]);
      return 0;
    }
  }
  // if ('N'==i_use_balance_ind[0]) 
  else if (!memcmp(i_use_balance_ind,"N",1))
  {
    // here I get a headache, this looks just at first glance risky. 
    for (j=1;balance_id[j]!=NULL,j<MAX_BUCKETS;j++)
    {
      b_ind=(j*8)+2;
      bc_ind=(j*8)+3;
      bs_ind=(j*8)+7;
      if (atoi(balance_id[j])!=1 && atoi( str[bc_ind] )!=0)
      {
        // length assumptions and memcpy when its only one byte
        // here u assume strlen(str[b_ind])>15 including \0
        memcpy(o_balance,str[b_ind],16);
        // here u assume strlen(str[bc_ind])>15 including \0
        memcpy(o_balance_change,str[bc_ind],16);
        // here, besides length assumption you could use a simple assignment
        // since its one byte
        memcpy(o_balance_sign,str[bs_ind],1);
        // a common practice is to set pointers that are freed to NULL.
        // maybe not necessary here since u return
        for(i=0;i<160;i++)
          free(str[i]);
        return 1;
      }
    }
    // suggestion do one function that frees your pointers to avoid dupl
    for(i=0;i<160;i++)
      free(str[i]);
    return 0;
  }
  for(i=0;i<160;i++)
    free(str[i]);
  return 0;
}

(或者不管你想做什么)

@dgna,首先我要确认的是,在一个存储桶中,我永远不会收到少于8个字段。唯一的问题是,在acse中,我有时可能不会收到20个存储桶。其次,balnace信息永远不会为null。由于我在检查其非null后从其他函数传递它,代码的本质是它在新的上下文和新的假设。防御性编码保护您免受调用您的东西的更改(和bug)。如果您担心性能开销,那么使用ASSERT(),它可以在开发过程中使用,并为生产编译
int foo( input* inbalance, output* outbalance )