如何修复运行时错误:加载类型为'const char的空指针
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何修复运行时错误:加载类型为'const char的空指针相关的知识,希望对你有一定的参考价值。
我需要编写在哈希表中加载字典的函数。我对错误消息感到困惑:c:37:20运行时错误:加载类型为'const char'的空指针,它在分段错误中运行。
我试图改变加载功能,但仍然没有帮助。并且还试图为哈希表分配内存,因为我认为问题可能在于内存泄漏。
` // Represents number of buckets in a hash table
#define N 26
// Represents a node in a hash table
typedef struct node
char word[LENGTH + 1];
struct node *next;
node;
// Represents a hash table
node *hashtable[N];
// Hashes word to a number between 0 and 25, inclusive, based on its first letter
unsigned int hash(const char *word)
// Allocates memory for hashtable
int *ht = malloc(26*sizeof(int));
if(!ht)
unload();
return false;
return tolower(word[0]) - 'a'; // this is error line 37:20
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
// Initialize hash table
for (int i = 0; i < N; i++)
hashtable[i] = NULL;
// Open dictionary
FILE *file = fopen(dictionary, "r");
if (file == NULL)
unload();
return false;
// Buffer for a word
char word[LENGTH + 1];
// Insert words into hash table
while (fscanf(file, "%s", word) != EOF)
for (int i = 0; i < N; i++ )
// Allocate memory for node for each new word
node *new_node = malloc(sizeof(node));
if (!new_node)
unload();
return false;
// Copies word into node
strcpy(new_node->word, word);
new_node->next = NULL;
// Hashes word
hash(new_node->word);
// Inserts word into linked list
if(hashtable[i] == 0)
hashtable[i] = new_node;
else if(hashtable[i] == new_node)
new_node->next = hashtable[i];
hashtable[i] = new_node;
// Close dictionary
fclose(file);
// Indicate success
return true;
加载字典时,函数加载应返回true。但是我得到了分段错误。这是否意味着我没有从加载功能得到正确的输出?
在
new_node->next = NULL; hash(new_node->word); // Inserts word into linked list if(hashtable[i] == 0) hashtable[i] = new_node; else if(hashtable[i] == new_node) new_node->next = hashtable[i]; hashtable[i] = new_node;
你不使用hash()的结果,你使用i而不是哈希结果作为哈希表中的索引,如果N大于26你读/写哈希表,在另一种情况下你不把这个词放在右边因为第一个在索引0,第一个在索引1等,无论它们的第一个字母是什么
注意else if(hashtable[i] == new_node)
从来都不是真的,事实上永远不会到达,因为if(hashtable[i] == 0)
总是正确的,因为你限制了要阅读的单词数量
必须是那样做最小的改变
int h = hash(new_node->word);
// Inserts word into linked list
if(hashtable[h] == 0)
hashtable[h] = new_node;
new_node->next = NULL;
else
new_node->next = hashtable[h];
hashtable[h] = new_node;
但实际上可以简化为:
int h = hash(new_node->word);
new_node->next = hashtable[h];
hashtable[h] = new_node;
注意我想你不会多次读同一个单词(它是一本字典)
去做
while (fscanf(file, "%s", word) != EOF)
是危险的,因为如果读取的字长于LENGTH则没有保护
假设LENGTH为32(单词可以存储32个字符,最后的空字符):
while (fscanf(file, "%32s", word) == 1)
没有理由拥有循环:
for (int i = 0; i < N; i++ ) ...
删除它(当然不是它的主体),所以:
while (fscanf(file, "%32s", word) == 1)
// Allocate memory for node for each new word
node *new_node = malloc(sizeof(node));
if (!new_node)
unload();
return false;
// Copies word into node
strcpy(new_node->word, word);
int h = hash(new_node->word);
new_node->next = hashtable[h];
hashtable[h] = new_node;
部分
// Initialize hash table
for (int i = 0; i < N; i++)
hashtable[i] = NULL;
因为全局哈希表初始化为0,所以没用
如果要重新加载字典,则需要先释放链表,然后重置为NULL
内存泄漏
hash中的malloc是无用的,只创建内存泄漏,删除它:
// Hashes word to a number between 0 and 25, inclusive, based on its first letter
unsigned int hash(const char *word)
return tolower(word[0]) - 'a';
警告如果第一个字母不是a-z或A-Z,则返回索引不是哈希表的有效索引
出于可读性原因,请用#define N 26
替换#define N ('z' - 'a' + 1)
添加缺失定义的提案:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define bool int
#define true 1
#define false 0
// Represents number of buckets in a hash table
#define N ('z' - 'a' + 1)
// Represent max word length
#define LENGTH 32
// Represents a node in a hash table
typedef struct node
char word[LENGTH + 1];
struct node * next;
node;
// Represents a hash table
node * hashtable[N];
// Hashes word to a number between 0 and 25, inclusive, based on its first letter
unsigned int hash(const char *word)
return tolower(word[0]) - 'a';
// probable goal : empty hashtable
void unload()
for (size_t i = 0; i != N; ++i)
while (hashtable[i] != NULL)
node * next = hashtable[i]->next;
free(hashtable[i]);
hashtable[i] = next;
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
// Open dictionary
FILE * file = fopen(dictionary, "r");
if (file == NULL)
return false;
// Buffer for a word
char word[LENGTH + 1];
// Insert words into hash table
while (fscanf(file, "%32s", word) == 1)
if (isalpha(word[0]))
// Allocate memory for node for each new word
node * new_node = malloc(sizeof(node));
if (!new_node)
unload();
return false;
// Copies word into node
strcpy(new_node->word, word);
int h = hash(new_node->word);
new_node->next = hashtable[h];
hashtable[h] = new_node;
// Close dictionary
fclose(file);
// Indicate success
return true;
int main(int argc, char ** argv)
if (argc != 2)
printf("Usage : %s <dictionary>\n", *argv);
else if (!load(argv[1]))
fprintf(stderr, "Error when loading '%s'\n", argv[1]);
else
puts("dictionary content");
for (size_t i = 0; i != N; ++i)
node * n = hashtable[i];
if (n != NULL)
printf("%c :", i + 'a');
do
printf(" %s", n->word);
n = n->next;
while (n != NULL);
putchar('\n');
unload();
编译和执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall d.c
pi@raspberrypi:/tmp $ cat d
alternate
bellow and
Below
dictionary
Hash main zombie
test
Zorro
pi@raspberrypi:/tmp $ ./a.out
Usage : ./a.out <dictionary>
pi@raspberrypi:/tmp $ ./a.out d
dictionary content
a : and alternate
b : Below bellow
d : dictionary
h : Hash
m : main
t : test
z : Zorro zombie
在valgrind下执行:
pi@raspberrypi:/tmp $ valgrind ./a.out d
==2370== Memcheck, a memory error detector
==2370== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2370== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2370== Command: ./a.out d
==2370==
dictionary content
a : and alternate
b : Below bellow
d : dictionary
h : Hash
m : main
t : test
z : Zorro zombie
==2370==
==2370== HEAP SUMMARY:
==2370== in use at exit: 0 bytes in 0 blocks
==2370== total heap usage: 13 allocs, 13 frees, 5,872 bytes allocated
==2370==
==2370== All heap blocks were freed -- no leaks are possible
==2370==
==2370== For counts of detected and suppressed errors, rerun with: -v
==2370== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
以上是关于如何修复运行时错误:加载类型为'const char的空指针的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 GCC 编译中的 const char * 构造函数转换链错误
在 Windows 机器上运行 RSKj 节点时如何修复 LevelDB 库加载错误?