ssse3 中的 strncpy 段错误,尽管所有参数看起来都是正确的

strncpy segfaults at ssse3 altough all parameters look correct

我的代码中有以下函数调用:

 strncpy(path_ptr,index_str,path_len);

通过 gdb 打印参数我得到:

gdb print path_ptr
# print path_ptr
# 7 = 0x7fffeb336636 \"7:0]\"

gdb print index_str
# print index_str
# 0 = \"0]\", '\0' <repeats 14 times>, \"\360\256\256\003\"

gdb print path_len
# print path_len
# 3 = 0x4

这意味着,如果我理解正确的话,这 4 个字符:\"0]\"、'\0' '\0' 将从 index_str 复制到 path_ptr .这看起来没问题,但是跨过这一行会出现以下段错误:

# Program received signal SIGSEGV, Segmentation fault.
# 0x0000003cd9f34cc3 in __strncpy_ssse3 () from /lib64/libc.so.6

知道为什么吗?完整的代码片段如下供参考:

static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag)
{
  char *path_ptr = path;
  int path_len, idx;
  svLogicVecVal bit_value;

  path_len = strlen(path);
  path_ptr = (char*)(path+path_len-1);

  if (*path_ptr != ']')
    return 0;

  while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[')
    path_ptr--;

  if (path_ptr == path || *path_ptr != ':')
    return 0;

  while(path_ptr != path && *path_ptr != '[')
    path_ptr--;

  if (path_ptr == path || *path_ptr != '[')
    return 0;

  int lhs, rhs, width, incr;

  // extract range from path
  if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) {
    char index_str[20];
    int i;
    path_ptr++;
    path_len = (path_len - (path_ptr - path));
    incr = (lhs>rhs) ? 1 : -1;
    width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1;
    vpi_printf((PLI_BYTE8*)"LHS %u RHS %u", lhs, rhs);

    // perform set for each individual bit
    for (i=0; i < width; i++) {
      sprintf(index_str,"%u]",rhs);
      strncpy(path_ptr,index_str,path_len);
      svGetPartselLogic(&bit_value,value,i,1);
      rhs += incr;
      if (!uvm_hdl_set_vlog(path,&bit_value,flag))
        return 0;
    }
    return 1;
  }
}

修改字符常量是未定义的,在许多现代编译器中,字符文字存储在只读数据-space 或代码-space 中。这两个都是"read only",表示无法写入存储。

由于 C++ 接受,为了向后兼容,分配一个带有字符常量的非常量 char*,你可以想出这样的东西:

 char *p = "Foo";
 char *q = "Bar";
 ... more code goes here so it's hard to see what p and q are.
 strcpy(p, q);

这会崩溃。

部分解决方案是始终如一地写:

const char *p = "Foo";
const char *q = "Bar"; 

然后编译器会指出 pconst 每当你试图将它传递给不期望的东西时 const。但它可能无法很好地与使用 char * 的旧式代码一起使用,而实际上它应该是 const char *,当然。

如果您确实希望能够修改这样的字符串:

char p[10] = "Foo";

谨防在 p's size tho' 之外写入。

更好的是,使用 C++ std::string,那么您就不会遇到这些问题。