【问题标题】:How to fix seg fault on first call to function LPS如何在第一次调用函数 LPS 时修复段错误
【发布时间】:2020-05-04 01:58:09
【问题描述】:

我正在尝试查找字符串s 的最长回文子序列,其中t 是测试用例的数量。我正在使用递归来查找回文子序列,并且在运行 gdb 时,我得到了以下输出:

Thread 3 hit Breakpoint 1, main () at lps.cpp:30
30      cin >> t;
(gdb) n
1
31      while(t--)
(gdb) 
33          string s;
(gdb) 
34          cin >> s;
(gdb) 
abcbd
35          int n = s.length();
(gdb) n
36          int lps = LPS(s, 0, n - 1);
(gdb) 

Thread 3 received signal SIGSEGV, Segmentation fault.
0x000000010000096b in LPS (s=..., 
    start=<error reading variable: Cannot access memory at address 0x7ffeef3fff28>, 
    end=<error reading variable: Cannot access memory at address 0x7ffeef3fff24>) at lps.cpp:7
7   {
(gdb) 

d∂∂这是我的程序,我使用递归来找到 lps。

我的逻辑:如果开始和结束字符相同,则减少结束并增加开始并递归字符串的其余部分

如果它们不匹配,则在一个调用中包含 start 和 exclude end,在另一个调用中排除 start 和 include end 并检查最长并返回最大值

#include <iostream>
#include <string>

using namespace std;

int LPS(string s, int start, int end) // start end both inclusive
{
    int n = s.length();
    if(n == 1) // single character left
        return 1;
    if(n == 0) // edge condition for 0 characters
        return 0;

    if(s[start] == s[end])
    {
        return 2 + LPS(s, start + 1, end - 1);
    }
    else
    {
        return max(LPS(s, start + 1, end), LPS(s, start, end - 1));
    }

}


int main() 
{

    int t;
    cin >> t;
    while(t--)
    {
        string s;
        cin >> s;
        int n = s.length();
        int lps = LPS(s, 0, n - 1);
        cout << lps << endl;
    }
    return 0;
}

【问题讨论】:

  • 如果你提供了一个实际构建的minimal reproducible example 会有所帮助。
  • 当您在调试器中捕获崩溃时,请检查回溯。是不是太长了?那么你的递归可能太深了,或者你有错误的退出条件(我猜这就是原因,对于任何两个或多个字符的字符串,它的长度何时会是01?)。跨度>
  • 使用注释行//int n = s.length(); 它甚至无法编译。请提供代码,我们不必修复拼写错误来重现任何内容。它也有很大帮助,你不依赖输入,而是硬编码一组导致错误的数据。或者至少告诉我们您使用了什么输入。

标签: c++ recursion segmentation-fault


【解决方案1】:
  1. 首先,您的代码无法编译,因此请取消注释 n 的初始化。

     cin >> s;
     int n = s.length();
     int lps = LPS(s, 0, n - 1);
    
  2. 您的递归没有正确的退出条件。请注意,您没有更改字符串 s,因此它的长度又名 n 每次都相同,您的退出条件实际上应该取决于 beginend - 它们在每次调用时都会发生变化

     if(begin == end) // single character left
        return 1;
     if(begin > end) // edge condition for 0 characters
        return 0;
    

【讨论】:

  • 第一个是什么意思?如果n 没有声明(因为它是在原始代码中注释的行),它甚至不会编译。当未注释的 n 在两次出现时都被赋值。
  • 与其尝试回答,不如简单地投票并评论问题不符合准则的原因,然后在修改后回答。
  • 即使 n 未注释它也不起作用... idk 为什么我评论了我的错误 ..
猜你喜欢
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 2019-09-24
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多