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";
然后编译器会指出 p
是 const
每当你试图将它传递给不期望的东西时 const
。但它可能无法很好地与使用 char *
的旧式代码一起使用,而实际上它应该是 const char *
,当然。
如果您确实希望能够修改这样的字符串:
char p[10] = "Foo";
谨防在 p
's size tho' 之外写入。
更好的是,使用 C++ std::string
,那么您就不会遇到这些问题。
我的代码中有以下函数调用:
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";
然后编译器会指出 p
是 const
每当你试图将它传递给不期望的东西时 const
。但它可能无法很好地与使用 char *
的旧式代码一起使用,而实际上它应该是 const char *
,当然。
如果您确实希望能够修改这样的字符串:
char p[10] = "Foo";
谨防在 p
's size tho' 之外写入。
更好的是,使用 C++ std::string
,那么您就不会遇到这些问题。