【问题标题】:C - strncpy usage - segfaultC - strncpy 用法 - 段错误
【发布时间】:2016-07-05 08:19:25
【问题描述】:
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() 的原因。

如果您知道如何解决,请告知。

【问题讨论】:

  • 开启编译器警告:-pedantic -Wall -Werror -std=c11.
  • 由于某种原因,测试被初始化为一个字符串数组(char**)。我想知道它最初是如何工作的。
  • 我想知道你怎么不会在最后一行的很多地方出现语法错误(0x66 是一个数字,而不是一个字符串,并且可能被隐式转换为一个确实无效的指针)
  • 不要尝试修改常量。
  • @PaulStelian 这是一个错字。我已经更新了我的问题

标签: c strncpy


【解决方案1】:

这里至少有三个两个可以得到段错误(一个建议是启用编译器警告 - 他们经常选择“愚蠢的错误”)。

问题是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]);
}

【讨论】:

    【解决方案2】:

    另一个答案给出了一个很好的理由(永远不要尝试修改字符串的 内容(str(n)cpy 会这样做))。

    我什至不确定您是否要将“字符”表示为字符串,尤其是第一个声明效果不佳(将字符串数组分配给字符串)。

    确定要解决这个问题需要做很多工作,但是您应该首先将“0x11”替换为“\x11”(即实际使用字符),将 strncpy 替换为仅赋值(真正的字符是原子类型,它可以直接赋值),最后改变change函数的参数,得到的是字符而不是字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多