【问题标题】:fix segmentation fault in trie c++修复 trie c++ 中的分段错误
【发布时间】:2019-07-04 17:18:25
【问题描述】:

我正在使用 trie 实现来存储和搜索 c++ 编程语言中的单词。在使用 search() 函数时,我在搜索特定单词时遇到了分段错误。检查结构是否为空时似乎发生了错误。

这是错误信息:

Program received signal SIGSEGV, Segmentation fault.
0x000055555555b2ff in search (this=0x55555577ee70, 
wordlist=0x55555577ef00, word="a1g6os") at test.cc:30
            if (!pCrawl->children[index])

这里是源代码:

#include <bits/stdc++.h> 
using namespace std; 
const int ALPHABET_SIZE = 26; 

struct TrieNode { 
struct TrieNode *children[ALPHABET_SIZE]; 

bool isEndOfWord; 
}; 



struct TrieNode *getNode(void) { 
    struct TrieNode *pNode =  new TrieNode; 
     pNode->isEndOfWord = false; 

    for (int i = 0; i < ALPHABET_SIZE; i++) 
        pNode->children[i] = NULL; 

    return pNode; 
} 



void insert(struct TrieNode *root, string key) { 
    struct TrieNode *pCrawl = root; 

    for (int i = 0; i < key.length(); i++) { 
        int index = key[i] - 'a'; 
        if (!pCrawl->children[index]) 
            pCrawl->children[index] = getNode(); 

        pCrawl = pCrawl->children[index]; 
   } 

   // mark last node as leaf 
   pCrawl->isEndOfWord = true; 
} 

// Returns true if key presents in trie, else 
// false 
bool search(struct TrieNode *root, string key) { 
    struct TrieNode *pCrawl = root; 

    for (int i = 0; i < key.length(); i++) { 
        int index = key[i] - 'a'; 
        if (!pCrawl->children[index]) 
             return false; 

        pCrawl = pCrawl->children[index]; 
    } 

    return (pCrawl != NULL && pCrawl->isEndOfWord); 
} 

int main() { 
    string keys[] = {"the", "a", "there", 
                "answer", "any", "by", 
                 "bye", "their" }; 
    int n = sizeof(keys)/sizeof(keys[0]); 

    struct TrieNode *root = getNode(); 

    for (int i = 0; i < n; i++) 
        insert(root, keys[i]); 

    // Search for different keys 
    search(root, "a1g6os")? cout << "Yes\n" : 
                     cout << "No\n"; 
    return 0; 
}

【问题讨论】:

  • 您显示的代码与调试器输出不匹配。调试器显示一个this 参数,它表示一个成员函数。您显示的代码中的函数都不是成员函数。创建minimal reproducible example 时,请确保它确实显示了您所询问的问题(当然,您显示的所有输出都来自该代码)。
  • 你需要检查pCrawl是否不是nullptr之前访问它的成员
  • 代码仅适用于小写字母(ALPHABET_SIZE 为 26,索引偏移 'a')。然而,您的搜索字符串包含数字。这将导致访问分配的数组之外!
  • 另请注意,key[i] - 'a' 之类的内容适用于 ASCII 编码,但 C++ 规范并未强制要求 ASCII。还有其他(尽管不那么常见)编码,这样的东西不起作用。
  • @JohnnyJohansson 你是对的,这个 trie 不支持数字。感谢您指出问题

标签: c++ trie


【解决方案1】:

@Some 程序员老兄和@JohnnyJohansson 都指出了根本原因。现场测试显示了代码在哪里读取了数组越界。实际上,一旦您了解发生了什么,修复就很容易了。如果您自己无法弄清楚,以下是固定代码。现场测试在这里cee.studio

#include<iostream>
using namespace std; 
const int ALPHABET_SIZE = 75; // increase the range

struct TrieNode { 
struct TrieNode *children[ALPHABET_SIZE]; 

bool isEndOfWord; 
}; 



struct TrieNode *getNode(void) { 
    struct TrieNode *pNode =  new TrieNode; 
     pNode->isEndOfWord = false; 

    for (int i = 0; i < ALPHABET_SIZE; i++) 
        pNode->children[i] = NULL; 

    return pNode; 
} 



void insert(struct TrieNode *root, string key) { 
    struct TrieNode *pCrawl = root; 

    for (int i = 0; i < key.length(); i++) { 
        int index = key[i] - '0';  // lower the low bound
        if (!pCrawl->children[index]) 
            pCrawl->children[index] = getNode(); 

        pCrawl = pCrawl->children[index]; 
   } 

   // mark last node as leaf 
   pCrawl->isEndOfWord = true; 
} 

// Returns true if key presents in trie, else 
// false 
bool search(struct TrieNode *root, string key) { 
    struct TrieNode *pCrawl = root; 

    for (int i = 0; i < key.length(); i++) { 
        int index = key[i] - '0';  // lower the low bound
        if (!pCrawl->children[index]) 
             return false; 

        pCrawl = pCrawl->children[index]; 
    } 

    return (pCrawl != NULL && pCrawl->isEndOfWord); 
} 

int main() { 
    string keys[] = {"the", "a", "there", 
                "answer", "any", "by", 
                 "bye", "their" }; 
    int n = sizeof(keys)/sizeof(keys[0]); 

    struct TrieNode *root = getNode(); 

    for (int i = 0; i < n; i++) 
        insert(root, keys[i]); 

    // Search for different keys 
    search(root, "a1g6os")? cout << "Yes\n" : 
                     cout << "No\n"; 
    return 0; 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    相关资源
    最近更新 更多