【问题标题】:Illegal instruction 4 when placing a function outside int main将函数放在 int main 之外时的非法指令 4
【发布时间】:2023-03-17 03:16:01
【问题描述】:

我刚刚开始学习 C 语言,但我的一个程序遇到了问题。

执行时出现错误:“Illegal instruction 4”:./dictionary large.txt

Large.txt 是一个包含 143091 个按字母顺序排列的单词的文件,每个单词都从新行开始。我正在尝试将它们全部加载到哈希表中,如果所有单词都成功加载,则返回 true。

如果 bool load() 中的代码在 int main 中并且 load() 不存在,则此代码适用于我。但是,一旦我将它放在 load() 函数中并从 main 中调用它,就会出现错误。

我会很感激这方面的帮助,因为非法指令的线程并不多。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

// Maximum length for a word
// (e.g., pneumonoultramicroscopicsilicovolcanoconiosis)
#define LENGTH 45

// Number of letters in the english alphabet
#define ALPHABET_LENGTH 26

// Default dictionary
#define DICTIONARY "large.txt"

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
} node;

// Number of buckets in hash table
const unsigned int N = ALPHABET_LENGTH;

// Hash table
node *table[N];

// Load function
bool load(char *dictionary);

// Hash function
int hash(char *word);

int main(int argc, char *argv[])
{
    // Check for correct number of args
    if (argc != 2 && argc != 3)
    {
        printf("Usage: ./speller [DICTIONARY] text\n");
        exit(1);
    }

    // Determine which dictionary to use
    char *dictionary = (argc == 3) ? argv[1] : DICTIONARY;

    bool loaded = load(dictionary);

    // TODO: free hashtable from memory

    return 0;
}

bool load(char *dictionary)
{
    // Open dictionary for reading
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        printf("Error 2: could not open %s. Please call customer service.\n", dictionary);
        exit(2);
    }

    // Initialize array to NULL
    for (int i = 0; i < N; i++)
        table[i] = NULL;

    // Declare and initialize variables
    unsigned int char_count = 0;
    unsigned int word_count = 0;
    char char_buffer;
    char word_buffer[LENGTH + 1];
    int hash_code = 0;
    int previous_hash_code = 0;

    // Declare pointers
    struct node *first_item;
    struct node *current_item;
    struct node *new_item;

    // Is true the first time the while loop is ran to be able to distinguish between hash_code and previous_hash_code after one loop
    bool first_loop = true;

    // Count the number of words in dictionary
    while (fread(&char_buffer, sizeof(char), 1, file))
    {

        // Builds the word_buffer by scanning characters
        if (char_buffer != '\n')
        {
            word_buffer[char_count] = char_buffer;

            char_count++;
        }
        else
        {
            // Increases word count each time char_buffer == '\n'
            word_count += 1;

            // Calls the hash function and stores its value in hash_code
            hash_code = hash(&word_buffer[0]);

            // Creates and initializes first node in a given table index
            if (hash_code != previous_hash_code || first_loop == true)
            {
                first_item = table[hash_code] = (struct node *)malloc(sizeof(node));
                if (first_item == NULL)
                {
                    printf("Error 3: memory not allocated. Please call customer service.\n");
                    return false;
                }

                current_item = first_item;
                strcpy(current_item->word, word_buffer);
                current_item->next = NULL;
            }
            else
            {
                new_item = current_item->next = (struct node *)malloc(sizeof(node));
                if (new_item == NULL)
                {
                    printf("Error 4: memory not allocated. Please call customer service.\n");
                    return false;
                }

                current_item = new_item;
                strcpy(current_item->word, word_buffer);
                current_item->next = NULL;
            }

            // Fills word buffer elements with '\0'
            for (int i = 0; i < char_count; i++)
            {
                word_buffer[i] = '\0';
            }

            // Signals the first loop has finished.
            first_loop = false;

            // Clears character buffer to keep track of next word
            char_count = 0;

            // Keeps track if a new table index should be initialized
            previous_hash_code = hash_code;
        }
    }

    return true;
}

// Hash in order of: 'a' is 0 and 'z' is 25
int hash(char *word_buffer)
{
    int hash = word_buffer[0] - 97;

    return hash;
}

提前谢谢你!

克里斯

【问题讨论】:

  • 使用调试器。至少它会立即为您提供触发崩溃的确切代码行。
  • 谢谢凯勒姆!您使用的是哪个调试器?
  • 取决于我当时编写的操作系统。 gdb 在 Linux 上,在 Windows 上是 Visual Studio,在 MacOS 上是 XCode。
  • strcpy(current_item-&gt;word, word_buffer); 看起来 word_buffer 至少在第一个单词中没有正确地以 NUL 结尾。这意味着strcpy 可以溢出一个或两个缓冲区。应该将缓冲区初始化为全零:char word_buffer[LENGTH + 1] = {0}; 或确保在单词末尾添加 NUL。
  • 欢迎来到stackoverflow :)。您已经找到了问题的答案,但我认为您的问题没有遵循 stackoverflow 的准则:您包含了大量代码,而您的问题相当于“请有人为我调试我的代码”。 stackoverflow 格式的一个好问题包括一个更具体的问题,您已将代码缩减为 minimal 可重现的示例。

标签: c hashtable illegal-instruction


【解决方案1】:

您应该使用node *table[ALPHABET_LENGTH]; 声明table 而不是node *table[N];

常量宏和const 变量之间存在区别,宏可以在常量表达式中使用,例如根据您的用例绑定的全局数组,而const 变量不能。

当您can see here 时,您说您正在使用的编译器 gcc,没有编译器标志,发出错误消息:

error: variably modified 'table' at file scope

您可以在 "static const" vs "#define" vs "enum" 中阅读更多关于这些差异和用例的信息,它有更多主题,例如 staticenum,但对于掌握这些概念之间的差异来说,这是一本不错的读物。

【讨论】:

  • 我添加了 char word_buffer[LENGTH + 1] = {0};修复了错误。我还应该将 node[N] 的大小更改为 node[ALPHABET_LENGTH] 吗?
  • @KLM54W 真的吗?你在哪里添加的?
  • Kaylum 在 cmets 中指出了这一点。 // 声明和初始化变量 unsigned int char_count = 0;无符号 int word_count = 0; char char_buffer; char word_buffer[LENGTH + 1] = {0}; int hash_code = 0; int previous_hash_code = 0;
  • 问题不是关于 C++,而是 node *table[N]; 的声明是 C 中的一个错误(静态数组的大小必须是整数常量表达式,其中不包括 const int 变量。但是许多编译器(例如:gcc、clang)都可以容忍这一点,并使用N 的正确值来调整数组的大小。
  • 也许可以问问你的老师这门课讲的是哪个 C 标准,因为例如 gcc 报告了所有官方 C 标准的错误。例如,最新的一个:gcc -std=c17 xx.c 给出了xx.c:28:7: error: variably modified ‘table’ at file scope。 gcc 的默认设置是使用 c17 的 gcc 特定方言,我看不出有什么理由哈佛会教它而不是标准 C。
猜你喜欢
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 2019-06-15
  • 2018-03-20
  • 2019-05-03
  • 1970-01-01
  • 2018-07-20
  • 2022-01-16
相关资源
最近更新 更多