c - Valgrind/内存错误

标签 c list memory linked-list valgrind

当我使用 valgrind 时,我在整个代码中反复收到以下错误。我不太清楚这些是什么意思,也无法识别未初始化的值。

==16795== Conditional jump or move depends on uninitialised value(s)
==16795==    at 0x4A06E8A: strcmp (mc_replace_strmem.c:412)
==16795==    by 0x4009C7: dictionary_add (libdictionary.c:44)
==16795==    by 0x40061B: main (part2.c:28)
==16795== 
==16795== Invalid write of size 1
==16795==    at 0x4A082E7: strcpy (mc_replace_strmem.c:303)
==16795==    by 0x400AA8: dictionary_add (libdictionary.c:57)
==16795==    by 0x40061B: main (part2.c:28)
==16795==  Address 0x4c361a3 is 0 bytes after a block of size 3 alloc'd
==16795==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==16795==    by 0x400931: node_newnode (libdictionary.c:28)
==16795==    by 0x400A8C: dictionary_add (libdictionary.c:54)
==16795==    by 0x40061B: main (part2.c:28)

我正在创建一个链表数据结构,这些是出现此内存错误时调用的函数。

//这里是节点和字典数据结构的构造。

typedef struct node
{
char* key;
char* value;
struct node* next;
}node;


typedef struct _dictionary_t
{
node* head;

} dictionary_t;

//首先创建一个新的字典

void dictionary_init(dictionary_t *d)
{
d->head = NULL;
d->head = malloc(sizeof(node));
node_init(d->head);
}

//使用 node_init 方法创建一个新节点。

void node_init(node *n)
{
n->key = NULL;
n->value =NULL;

n->key = malloc(sizeof(char));
n->value = malloc(sizeof(char));
n->next = NULL;
}

//这个新的节点方法是在原来的初始化之后(我们在添加新项的时候)使用的

void node_newnode(node *n, int x, int y)
{
n->key = NULL;
n->value = NULL;

n->key = malloc(x*sizeof(char));
n->value = malloc(y*sizeof(char));
n->next = NULL;
}

//在这种情况下,也调用此函数以将“key”和“value”添加为一对。

int dictionary_add(dictionary_t *d, const char *key, const char *value)
{
node *current;
current =  d->head;
if(strcmp(current->key,key)==0)
        return -1;
while(current->next != NULL){
        current=current->next;
        if(strcmp(current->key,key)==0)
                return -1;
}
        current->next = NULL;
        current->next = malloc(sizeof(node));

        node_newnode(current->next,strlen(key),strlen(value));

        current = current->next;
        strcpy((current->key), key);
        strcpy((current->value),value);
        return 0;
}

任何人都知道为什么我会收到这些错误。到目前为止,main 方法只创建了一个字典并调用了 add 函数。 Valgrind 在 8 个函数调用过程中报告了超过 38 个上下文的 45+ 个错误。我认为这些可能是我反复犯的小错误。

我现在也遇到了同样的错误。 valgrind --track-origins=yes 命令将其跟踪到以下函数中的堆栈分配:

int dictionary_parse(dictionary_t *d, char *key_value)
{
char* colon;
char* space;
colon = key_value;
space = key_value;

space++;

int key_length = -1; //Default key length to check for failure

int i=0;
int j=0;   // Loop variables
int k=0;

int length = strlen(key_value);

for(i=0;i<length-2;i++){
        if(*colon == ':' && *space == ' '){
                key_length = i;
                break;
        }
        colon++;
        space++;
}

if(key_length == -1 || key_length == 0)
        return -1;

int value_length = length-2-key_length;

colon = key_value;


char key_word[key_length];
key_word[0] = '\0';
char value_word[value_length];
value_word[0] = '\0';

for(j=0;j<key_length;j++){
key_word[j] = *colon;
colon++;
}

space++;

for(k=0; k<value_length;k++){
value_word[k] = *space;
space++;
}


char* finalkey[key_length];
strcpy((char*)finalkey,key_word);
char* finalvalue[value_length];
strcpy((char*)finalvalue,value_word);

dictionary_add(d,(char*)finalkey,(char*)finalvalue);    

return 0;

}

谢谢, -新程序员

最佳答案

第一个错误(“条件跳转或移动取决于未初始化的值”)是因为 current->key 指向的字符从未被初始化。您在 node_init() 中为它分配了一个字节,但实际上您从未将该字节设置为任何内容。如果您希望 head 节点的 key 充当空字符串,请像这样更改 node_init():

n->key = malloc(sizeof(char));
n->key[0] = '\0';

第二个错误(“大小为 1 的无效写入”)是因为您的 node_newnode() 函数分配的字节比字符串所需的少一个字节。 strlen(key) 计算字符串中的实际字符数,但空终止符需要多一个字节。使用:

node_newnode(current->next,strlen(key) + 1,strlen(value) + 1);

(但我个人只是将 keyvalue 传递给 node_newnode(),并让它完成分配和 strcpy()).

关于c - Valgrind/内存错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3645109/

相关文章:

c - 增量运算符在 do while 循环中如何工作?

c++ - 当前内存使用显示总是比任务管理器多 ~14MB

c++ - mmap问题,分配大量内存

c - 变量名如何存储在 C 中的内存中?

c - 将 char 指针数组传递给 C 中的函数?

C 程序卡住,不进入 main()

c - C 中的内存管理(分配)

python - 有没有更快的方法来检查一个数字是否在一个区间内?

string - 解析命令行参数来处理 bash 中的文件列表?

c# - 如何使用正则表达式从列表中提取字符串匹配项?