C - strncpy 用法 - 段错误
C - strncpy usage - segfault
char *test={"0x11","0x12","0x13","0x00","0x00"};
void change(char* test1, char* test2){
strncpy(test[3], test1, 4);
strncpy(test[4], test2, 4);
}
chage("0x55","0x66");
我可以直接把字符赋给数组元素。但是,它会导致内存泄漏。这就是我使用 strncpy()
的原因。
如果您知道如何修复,请告知。
这里至少有三两个你可以得到段错误(一个建议是启用编译器警告 - 他们经常选择 "stupid mistakes")。
问题是 test
可能被误报了,应该是:
char *test[]={"0x11","0x12","0x13","0x00","0x00"};
您使用 char*
数组初始化 char*
,这意味着您使用该数组中的第一个指针初始化 test
- 这意味着 test
将指向到字符串文字 "0x11"
,因此当您使用 test[3]
作为 strncpy
的参数时,您将发送 1
,它被转换为一个指针(可能指向地址 0x31
). strncpy
然后会尝试写入最有可能不允许的地址。您在这里有将近第四个原因,如果您使用了 test[5]
,您将要求访问超出字符串末尾的内容,这是不允许的(您可以访问 test[4]
因为它是字符串的终止空值)。
即使您解决了这些问题,仍然存在问题,因为 test[3]
和 test[4]
是使用字符串文字初始化的。然后 strncpy
将尝试修改未定义行为的字符串文字 - 段错误是因为 test[3]
和 test[4]
驻留在只读内存中(允许它们位于只读内存中是修改字符串文字是未定义行为的原因之一)。
你本来可以做的是确保你在 test
中有可写的副本,这在 C 中可能不是那么简单。一个正常的解决方案是有一个函数(你必须调用手动)设置 test
,还有一个将其拆除:
void init_test(void) {
int j;
for(j=0; j<sizeof(test)/sizeof(test[0]); j++)
test[j] = strdup(test[j]);
}
void init_fini(void) {
int j;
for(j=0; j<sizeof(test)/sizeof(test[0]); j++)
free(test[j]);
}
另一个答案给出了一个很好的理由(永远不要尝试修改字符串的内容(str(n)cpy 会那样做))。
我什至不确定您想将 "characters" 表示为字符串,尤其是第一个声明效果不佳(将字符串数组分配给字符串)。
确实需要做很多工作才能解决这个问题,但您应该首先将“0x11”替换为“\x11”(即实际使用字符),仅通过赋值替换 strncpy(真正的字符是原子的可以直接赋值的类型),最后将 change 函数的参数改为获取字符而不是字符串。
char *test={"0x11","0x12","0x13","0x00","0x00"};
void change(char* test1, char* test2){
strncpy(test[3], test1, 4);
strncpy(test[4], test2, 4);
}
chage("0x55","0x66");
我可以直接把字符赋给数组元素。但是,它会导致内存泄漏。这就是我使用 strncpy()
的原因。
如果您知道如何修复,请告知。
这里至少有三两个你可以得到段错误(一个建议是启用编译器警告 - 他们经常选择 "stupid mistakes")。
问题是 test
可能被误报了,应该是:
char *test[]={"0x11","0x12","0x13","0x00","0x00"};
您使用 char*
数组初始化 char*
,这意味着您使用该数组中的第一个指针初始化 test
- 这意味着 test
将指向到字符串文字 "0x11"
,因此当您使用 test[3]
作为 strncpy
的参数时,您将发送 1
,它被转换为一个指针(可能指向地址 0x31
). strncpy
然后会尝试写入最有可能不允许的地址。您在这里有将近第四个原因,如果您使用了 test[5]
,您将要求访问超出字符串末尾的内容,这是不允许的(您可以访问 test[4]
因为它是字符串的终止空值)。
即使您解决了这些问题,仍然存在问题,因为 test[3]
和 test[4]
是使用字符串文字初始化的。然后 strncpy
将尝试修改未定义行为的字符串文字 - 段错误是因为 test[3]
和 test[4]
驻留在只读内存中(允许它们位于只读内存中是修改字符串文字是未定义行为的原因之一)。
你本来可以做的是确保你在 test
中有可写的副本,这在 C 中可能不是那么简单。一个正常的解决方案是有一个函数(你必须调用手动)设置 test
,还有一个将其拆除:
void init_test(void) {
int j;
for(j=0; j<sizeof(test)/sizeof(test[0]); j++)
test[j] = strdup(test[j]);
}
void init_fini(void) {
int j;
for(j=0; j<sizeof(test)/sizeof(test[0]); j++)
free(test[j]);
}
另一个答案给出了一个很好的理由(永远不要尝试修改字符串的内容(str(n)cpy 会那样做))。
我什至不确定您想将 "characters" 表示为字符串,尤其是第一个声明效果不佳(将字符串数组分配给字符串)。
确实需要做很多工作才能解决这个问题,但您应该首先将“0x11”替换为“\x11”(即实际使用字符),仅通过赋值替换 strncpy(真正的字符是原子的可以直接赋值的类型),最后将 change 函数的参数改为获取字符而不是字符串。