【问题标题】:Segmentation fault on char string reference字符字符串引用的分段错误
【发布时间】:2012-09-21 04:13:52
【问题描述】:

我有一个小的 C++ 函数可以将字符串反转:

void reverse1(string& s, int start, int end) {
  if (s.empty()) return;
  char tmp;

  while (start < end) {
    tmp = s[end];
    s[end] = s[start];
    s[start] = tmp;
    ++start;
    --end;
  }
}

这个功能很好用。但是,当我如下用 c 重写它时,我在语句 11 上遇到了段错误。

  5 void reverse2(char *s, int start, int end) {
  6   if (!s) return;
  7   char tmp;
  8   
  9   while (start < end) {
 10     tmp = s[end];
 11     *(s + end) = *(s + start);
 12     *(s + start) = tmp;
 13     ++start;
 14     --end;
 15   } 
 16 } 

调用函数的驱动程序:

int main() {
  /* Flavor1 works */
  string a = "hello world2012!";
  reverse1(a, 0, a.length() - 1);

  /* Flavor2 does not - segmentation fault */ 
  char *b = "hello world2012!";
  reverse2(b, 0, strlen(b) - 1);
}

我使用 gcc v 4.6.1 来编译我的程序。使用 gdb 单步执行代码时,程序在运行时因分段错误而崩溃。

char 字符串 s 不是 const。有人可以建议这里发生了什么吗?我该如何解决这个问题。谢谢。

更新: reverse2 函数在字符串文字上调用。问题是我试图修改字符串文字。正如 Jim 和 H2CO3 所指出的,这是一种未定义的行为。

现在用字符串字面量初始化的字符串对象 (a) 和字符串字面量 (b) 之间的确切区别是什么?

【问题讨论】:

  • 你知道你可以在 C 中使用 s[end]s[start],对吧?
  • 尝试s[end] = s[start]; 等,而不是进入显式指针算法。
  • 你的函数看起来没问题,假设 startend 是有效的字符串索引,s 是一个可写字符串——你可能想检查函数的呼叫者。另请注意,!s 只是检查s 是否为空指针,而不是查看s 是否为空字符串;你需要!s[0]
  • 您应该发布如何调用反向函数,如何构建字符串以及开始和结束索引的值以帮助您更好。
  • 我敢打赌你是在字符串文字上调用你的函数...

标签: c character


【解决方案1】:

这取决于你如何调用你的例程。如果end 是数组的长度,这在C 中很常见,那么s[end] 不是一个有效的引用……它是s 之外的一个字符。

另外,!s 不等同于 C++ s.empty ... 它测试指针是否为 NULL,而不是字符串是否为空 -- 为此,请使用 !*s!s[0]、@987654328 @、strlen(s) == 0

char 字符串 s 不是 const。

如果它是一个字符串常量,它无论如何都会失败;写入这样的字符串是未定义的行为。

【讨论】:

  • 也许值得注意的是,顶部条件可以是s &amp;&amp; s[0](或任何变体),以确保它不是空指针并且包含字符串。
【解决方案2】:

你可以改写如下代码

void reverse(char *s, int start, int end) {
  if (!s) return;
  char tmp;

  if( end >= strlen(s) )
      end = strlen(s)-1;

  while (start < end) {
    tmp = s[end];
    *(s + end) = *(s + start);
    *(s + start) = tmp;
    ++start;
    --end;
  } 
} 

【讨论】:

  • 有什么意义?如果end 错误,所做的只是隐藏一个错误;这是非常糟糕的做法。最好是assert(start &gt;= 0 &amp;&amp; end &lt; strlen(s)),但它很奢侈,不是 OP 的问题。如果您要重写它,请将毫无意义的冗长 *(s + x) 替换为 s[x]
猜你喜欢
  • 2012-11-14
  • 2013-05-26
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多