c - 无法从 valgrind 跟踪内存问题
问题描述
我一直在试图找出我做错了什么,但我认为我在导致内存问题的代码中存在不止一个问题。我已经评论了我能够跟踪的部分。我认为我在指针方面存在一些问题,在哪里使用什么,也许还有其他一些小问题。
我的主要代码
int main(int argc, char ** argv){
printf("In Main\n");
if(argc != 7){
printf("args doesn't match expected value\n");
return EXIT_FAILURE;
}
FILE *fptr = fopen(argv[1], "rb");
if(fptr == NULL){
return EXIT_FAILURE;
}
long int size_compressed; //size_compressed: Number of bytes in compressed file
long int size_topology; //size_topology: Number of bytes topology uses
long int size_original; //size_original: Number of bytes in the uncompressed file
fread(&size_compressed, sizeof(long int) , 1, fptr);
fread(&size_topology, sizeof(long int), 1, fptr);
fread(&size_original, sizeof(long int), 1, fptr);
int size = sizeof(char)* sizeof(long int) * size_topology;
printf("Size Compressed: %ld\n", size_compressed);
printf("Size Topology: %ld\n", size_topology);
printf("Size Original: %ld\n", size_original);
unsigned char *buffer;
int *val;
buffer = (unsigned char*) malloc(sizeof(unsigned char) * size_topology);
size_t bytes_read = fread(buffer, sizeof(unsigned char), size_topology, fptr);
//val = (int*) malloc(sizeof(int) * (size_topology));
val = (int*) malloc(size);
fclose(fptr);
if(bytes_read != size_topology){
printf("Topology size and read bytes don't match!");
}
for(int i=0; i < size_topology; i++){
val[i] = buffer[i];
}
char *toVal; //toVal: char array of 8 to store every bit of a byte
char *all_topology; //all_topology: char array of 8 * size_topology to store ALL bits of topology.
int j; //j: index for all_topology
// toVal = (char*) malloc(sizeof(char)* sizeof(int));
// all_topology = (char*) malloc(size);
toVal = (char*) malloc(size);
all_topology = (char*) malloc(size);
//For Loop where conversion of the bytes in val to bits happen, output is stored in all_topology
for(int i=0; i < size_topology; i++){
j = i*8;
byte_to_bits(val[i], toVal);
for(int k=0; k< 8;k++){
all_topology[j] = toVal[k];
printf("%d", all_topology[j]);
j++;
}
printf("\n");
}
//no memory issues up to here
Snode* stack = NULL;
int numOfBytes = byte_to_char(all_topology, &stack, size);
Tnode* tmp = NULL;
while(1){
if(isEmpty(stack)){
break;
} else{
tmp = pop(&stack);
}
}
remove_zeroes(stack);
printf("NumOfBYtes: %d\n", numOfBytes);
Tnode* node;
Snode* reverse_stack;
int flag = 1;
while(flag){
node = pop(&stack);
if(node == NULL){
break;
}
printf("%c\n", node->id);
push(&reverse_stack, node);
}
// printf("\n");
// Snode* tmp = reverse_stack;
// while(reverse_stack != NULL){
// char a = peek(&tmp);
// printf("%c", a);
// tmp = tmp->next;
// }
// printf("\n");
// Topolgy created in the same format as pg6 line1. into stack "reverse_stack"
// Lots of memory errors and memory lost
// Still need to build tree
//free(node);
free(all_topology);
free(toVal);
// free(node);
free(buffer);
free(val);
return EXIT_SUCCESS;
}
Valgrind 输出
==10990==
==10990== HEAP SUMMARY:
==10990== in use at exit: 552 bytes in 23 blocks
==10990== total heap usage: 53 allocs, 30 frees, 1,778 bytes allocated
==10990==
==10990== Searching for pointers to 23 not-freed blocks
==10990== Checked 70,128 bytes
==10990==
==10990== 168 bytes in 7 blocks are definitely lost in loss record 1 of 3
==10990== at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==10990== by 0x400D53: createNode (tree.c:9)
==10990== by 0x400868: byte_to_char (pa2.c:46)
==10990== by 0x400C4A: main (pa2.c:152)
==10990==
==10990== 192 bytes in 8 blocks are definitely lost in loss record 2 of 3
==10990== at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==10990== by 0x400D53: createNode (tree.c:9)
==10990== by 0x40089B: byte_to_char (pa2.c:52)
==10990== by 0x400C4A: main (pa2.c:152)
==10990==
==10990== 192 bytes in 8 blocks are definitely lost in loss record 3 of 3
==10990== at 0x4C2C089: calloc (vg_replace_malloc.c:762)
==10990== by 0x400D53: createNode (tree.c:9)
==10990== by 0x400941: byte_to_char (pa2.c:69)
==10990== by 0x400C4A: main (pa2.c:152)
==10990==
==10990== LEAK SUMMARY:
==10990== definitely lost: 552 bytes in 23 blocks
==10990== indirectly lost: 0 bytes in 0 blocks
==10990== possibly lost: 0 bytes in 0 blocks
==10990== still reachable: 0 bytes in 0 blocks
==10990== suppressed: 0 bytes in 0 blocks
==10990==
==10990== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
基于valgrind的输出,我还添加了下面错误中提到的功能。
byte_to_char
int byte_to_char(char *topology, Snode** stack, int size){
int numOfBytes = 0;
char ascii_concat[8];
unsigned char ascii_val = 0;
int countChar =0;
Tnode* node;
//char char_top[80];
for(int i=0; i < size; i++){
if(topology[i] == 0){
//char_top[i] = 48; //ASCII Value of 0
node = createNode(48, 0);
push(stack, node);
numOfBytes++;
} else{
ascii_val = 0xff;
//char_top[i] = 49; //ASCII Value of 1
node = createNode(49, 1);
push(stack, node);
numOfBytes++;
i++; //skip the leaf node indicator
countChar++;
for(int j=0; j<8; j++){
ascii_concat[j] = topology[i++];
}
i--;
for(int j=0; j<8; j++){
if(ascii_concat[j] == 0){
ascii_val = (1 << (j)) ^ ascii_val;
}
}
//printf("%c\n", ascii_val);
//Create leaf node
//char_top[i] = ascii_val;
node = createNode(ascii_val, 2);
push(stack, node);
numOfBytes = numOfBytes+8;
//count characters in header
}
countChar++;
}
// printf("chars\n");
// for(int i=0;i < 24; i++){
// printf("%c", char_top[i]);
// }
free(node);
return numOfBytes;
}
创建节点
Tnode *createNode(int key, int bal)
{
Tnode *n = (Tnode *)calloc(1, sizeof(Tnode));
//Tnode *n = (Tnode*) malloc(sizeof(Tnode));
n->key = key;
n->balance = bal;
n->left = NULL; //?
n->right = NULL; //?
return n;
}
解决方案
在 for 循环中的函数 byte_to_char 中,您在调用 createNode 函数时分配了 3 次内存。但是这个内存永远不会被释放,所以 valgrind 会发出内存泄漏的信号。您必须在循环中释放节点变量,否则每次更改指针的值时都会丢失地址并且您将无法释放内存。
因为你不能在循环中释放,也许你应该发送你的节点的副本,然后释放你的节点变量
Tnode *my_duplicate_node(const Tnode *src)
{
Tnode *dest = calloc(sizeof(Tnode), 1);
memcpy(dest, src, sizeof(Tnode));
return dest;
}
for(int i=0; i < size; i++){
if(topology[i] == 0){
node = createNode(48, 0);
push(stack, my_duplicate_node(node));
free(node);
} else{
[...]
node = createNode(49, 1);
push(stack, my_duplicate_node(node));
free(node);
}
}
它不存在为结构复制内存块的任何函数,因此您可以尝试类似 my_duplicate_node 函数
推荐阅读
- abap - 服务条目表(SES)中未填写的发布组和发布策略字段
- components - 如何计算平均燃耗和平均燃耗?
- flutter - 参数类型“int”不能分配给参数类型“String”
- wordpress - Git 操作是在 Web 服务器上还是在本地文件系统上?
- laravel - 云功能的替代品
- ios - Firebase 动态链接未打开 IOS 应用程序
- join - 自联接查询与其他表中的引用
- c# - Mailkit 是否支持发送匿名电子邮件?
- javascript - 应用程序的 indexOf() 无法正常工作
- javascript - 在以下代码中使用 asyn/await 的最佳方式