问题描述
在 Valgrind 中运行程序,它表示在转换时出现无效读入的8号大小"结构的指针.它和calloc有关吗?如果按原样读取,则为(nil).
Running the program in Valgrind, it says that there is an "Invalid read of size 8" at the transition pointer of the struct. It has something to do with the calloc? It is (nil) if it is read as is.
具有结构(称为trie),其用法如下:
Having a struct (called trie), it is used as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
const int MAX_SIZE = 20;
struct _trie {
int maxNode;
int nextNode;
int** transition;
char* fin;
};
typedef struct _trie * Trie;
Trie createTrie (int maxNode){
Trie trie;
trie = (Trie) malloc(sizeof(Trie));
printf("size of trie: %lu, size of the struct: %lu, size of _trie: %lu\n",sizeof(trie),sizeof(Trie), sizeof(struct _trie));
trie->maxNode = maxNode;
printf("maxNode = %d, size of maxNode: %lu\n",trie->maxNode,sizeof(trie->maxNode));
printf("size of nextNode : %lu, size of transition: %lu, size of fin: %lu\n",
sizeof(trie->nextNode),sizeof(trie->transition),sizeof(trie->fin));
在这里,当valgrid尝试读取时,它说无效的8号读取":
Here, when valgrid tries to read, it says "Invalid read of size 8":
//invalid read
printf("transitions points to: %p, address: %p\n",trie->transition,&trie->transition);
来自char * fin的相同消息:
Same message from the char * fin:
//invalid read
printf("fin points to: %p, address: %p\n",trie->fin,&trie->fin);
getchar();
trie->transition = (int**)calloc(maxNode,sizeof(int*));
printf("trie->transition done.\n");
printf("transitions points to: %p, address: %p\n",trie->transition,&trie->transition);
if(trie->transition == NULL){
printf("null for trie->transition\n");
exit(0);
}
printf("Size of transition: %lu, size of int:%lu, pointer: %p\n\n",sizeof(trie->transition),sizeof(int),trie->transition);
for(int counter = 0; counter < maxNode; ++counter){
trie->transition[counter] = calloc(UCHAR_MAX,sizeof(int));
if(trie->transition[counter] == NULL){
printf("null for trie->transition[%d]\n",counter);
exit(0);
}
//printf("size of transition[%d]: %lu\n",counter,sizeof(trie->transition[counter]));
}
printf("\nFilling up trie->transition\n");
for(int counter = 0; counter < maxNode; ++counter){
for(int counter2 = 0; counter2 < UCHAR_MAX; ++counter2){
trie->transition[counter][counter2] = -1;
//printf("size of transition[%d][%d]: %lu, value: %d\n",counter,counter2,sizeof(trie->transition[counter]),trie->transition[counter][counter2]);
}
//getchar();
}
return (trie);
}
void free_all(Trie trie){
for(int counter = 0; counter < trie->maxNode; ++counter){
free(trie->transition[counter]);
}
free(trie->transition);
free(trie);
}
int main(int argc, char *argv[]){
Trie trie = createTrie(MAX_SIZE);
free_all(trie);
return (0);
}
Valgrind输出:
Valgrind output:
==3079== Memcheck, a memory error detector
==3079== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3079== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==3079== Command: ./debug_test
==3079==
size of trie: 8, size of the struct: 8, size of _trie: 24
maxNode = 20, size of maxNode: 4
size of nextNode : 4, size of transition: 8, size of fin: 8
==3079== Invalid read of size 8
==3079== at 0x1088AD: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
transitions points to: (nil), address: 0x5201048
==3079== Invalid read of size 8
==3079== at 0x1088D1: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201050 is 8 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
fin points to: (nil), address: 0x5201050
==3079== Invalid write of size 8
==3079== at 0x108907: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
trie->transition done.
==3079== Invalid read of size 8
==3079== at 0x108923: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
transitions points to: 0x5201910, address: 0x5201048
==3079== Invalid read of size 8
==3079== at 0x10893F: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
==3079== Invalid read of size 8
==3079== at 0x108962: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
Size of transition: 8, size of int:4, pointer: 0x5201910
==3079== Invalid read of size 8
==3079== at 0x108991: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
==3079== Invalid read of size 8
==3079== at 0x1089B9: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
Filling up trie->transition
==3079== Invalid read of size 8
==3079== at 0x108A20: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
==3079== Invalid read of size 8
==3079== at 0x108A84: free_all (in /projects/trie/debug_test)
==3079== by 0x108AF8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
==3079== Invalid read of size 8
==3079== at 0x108AB3: free_all (in /projects/trie/debug_test)
==3079== by 0x108AF8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079==
==3079==
==3079== HEAP SUMMARY:
==3079== in use at exit: 0 bytes in 0 blocks
==3079== total heap usage: 24 allocs, 24 frees, 22,616 bytes allocated
==3079==
==3079== All heap blocks were freed -- no leaks are possible
==3079==
==3079== For counts of detected and suppressed errors, rerun with: -v
==3079== ERROR SUMMARY: 5167 errors from 11 contexts (suppressed: 0 from 0)
推荐答案
==3079== Invalid read of size 8
==3079== at 0x1088AD: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3079== by 0x108835: createTrie (in /projects/trie/debug_test)
==3079== by 0x108AE8: main (in /projects/trie/debug_test)
这表示您的代码正在尝试从无效地址中读取8字节的值.
This says your code is trying to read an 8-byte value from an invalid address.
此地址紧接在通过createTrie
中的malloc
分配的8字节块之后.换句话说,这一行:
This address is just after an 8 byte block allocated via malloc
in createTrie
. In other words, this line:
trie = (Trie) malloc(sizeof(Trie));
为什么认为trie
指向仅8个字节的内存?因为您分配了sizeof (Trie)
个字节,而Trie
是
Why does it think trie
points to only 8 bytes of memory? Because you allocated sizeof (Trie)
bytes, and Trie
is
typedef struct _trie * Trie;
换句话说,当您打算为整个结构分配足够的内存时,便为指针分配了内存.
Or on other words, you allocated memory for a pointer when you meant to allocate enough memory for a whole struct.
出于这个原因,强烈建议不要将指针隐藏在typedef后面.
It is strongly recommended not to hide pointers behind typedefs, for exactly this reason.
建议的解决方法:
typedef struct Trie Trie;
struct Trie {
int maxNode;
int nextNode;
int** transition;
char* fin;
};
Trie *createTrie(int maxNode) {
Trie *trie;
trie = malloc(sizeof *trie);
注意:
- 我们为
struct Trie
和(裸露的)Trie
使用了相同的名称(Trie
),因为其他任何事情都会造成混淆. - 使用
*
,所有指针都被明显地声明为指针. - 我们不强制转换
malloc
的返回值,因为那将是另一个潜在的错误来源. - 无论如何声明
trie
,我们都使用sizeof *trie
来获取trie
所指向类型的正确字节数.
- We use the same name (
Trie
) for bothstruct Trie
and (bare)Trie
because anything else is needlessly confusing. - All pointers are visibly declared as pointers, with
*
. - We don't cast the return value of
malloc
because that would be another potential source of errors. - We use
sizeof *trie
to get the correct number of bytes in the typetrie
is pointing to, no matter howtrie
is declared.
这篇关于为什么读取结构指针字段无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!