Valgrind 消息:地址 XXX 在 r-x 映射文件 <fielpath> 段中
Valgrind message : Address XXX is in a r-x mapped file <fielpath> segment
正在学习C的malloc和自定义结构相关的free heap memory
我遇到的问题
对于下面的代码,我经常得到 segment fault
。
使用 valgrind
分析显示:==12999== Address 0x108b4b is in a r-x mapped file <folder_path> segment
==12999==
完整输出:
Name : Amy
Date of Birth: 1989 9 21
Name : echo
Date of Birth: 1989 9 21
Name : echo
Date of Birth: 1989 9 21
Name : echo Address 0x5580be70e270
Date of Birth: 1989 9 21
Their address : 0x5580be70e260 0x5580be70e264 0x5580be70e268
Name : echo Address 0x5580be70e270
Date of Birth: 1989 9 21
Their address : 0x5580be70e260 0x5580be70e264 0x5580be70e268
free p->name
Segmentation fault (core dumped)
我做的分析
我使用 valgrind
来尝试找到结果:
valgrind --tool=memcheck --leak-check=full ./person2
输出显示为:
Their address : 0x522d040 0x522d044 0x522d048
Name : echo Address 0x522d050
Date of Birth: 1989 9 21
Their address : 0x522d040 0x522d044 0x522d048
free p->name
==12999== Invalid free() / delete / delete[] / realloc()
==12999== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12999== by 0x108894: Person_destruct (person2.c:33)
==12999== by 0x108A2F: main (person2.c:74)
==12999== Address 0x108b4b is in a r-x mapped file /folder/path segment
==12999==
freed p->name
free p
freed p
==12999==
==12999== HEAP SUMMARY:
==12999== in use at exit: 4 bytes in 1 blocks
==12999== total heap usage: 3 allocs, 3 frees, 1,052 bytes allocated
==12999==
==12999== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==12999== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12999== by 0x108817: Person_construct (person2.c:16)
==12999== by 0x1089CC: main (person2.c:64)
==12999==
==12999== LEAK SUMMARY:
==12999== definitely lost: 4 bytes in 1 blocks
==12999== indirectly lost: 0 bytes in 0 blocks
==12999== possibly lost: 0 bytes in 0 blocks
==12999== still reachable: 0 bytes in 0 blocks
==12999== suppressed: 0 bytes in 0 blocks
==12999==
==12999== For counts of detected and suppressed errors, rerun with: -v
==12999== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
我的理解是 *p3
指向与 p1
完全相同的内存片(Person_address_print()
证明了这一点,因此我只是显式地 destruct p1
以避免两次破坏相同的堆内存。)
我还尝试让 p3->name = "ada";
确保分配的字符串仍在之前的长度 (3) 内,或者在调用 Person_destruct(p1)
之前显式设置 p3 == NULL
;发生相同的段错误:(
密码
这是代码。代码基本上是这样的:
一种。自定义一个结构Person
b. (in main
)为Person
构造对象,销毁它们并打印相关属性。
// person.h
#ifndef PERSON_H
#define PERSON_H
typedef struct
{
int year;
int month;
int date;
char * name; // name is a ponter b/c name length is unknown
} Person;
Person * Person_construct(int y, int m, int d, char * n);
void Person_destruct(Person *p);
void Person_print(Person * p);
#endif
#include "person.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Person *Person_construct(int y, int m, int d, char *n)
{
Person *p = NULL;
p = malloc(sizeof (Person));
if (p == NULL) // malloc failed
{
return NULL;
}
p->year= y;
p->month = m;
p->date = d;
p->name = malloc(sizeof(char) * (strlen(n) + 1));
// + 1 for the neding char '[=14=]'
if ((p->name) == NULL)// malloc failed, just return
{
free(p);
return NULL;
}
strcpy(p->name, n);
return p;
}
void Person_destruct(Person *p)
{
// p->name must be freed befoer p is freed
if (p->name != NULL)
{
printf("free p->name \n");
free(p->name);
printf("freed p->name \n");
}
if (p != NULL)
{
printf("free p \n");
free(p);
printf("freed p \n");
}
}
void Person_print(Person *p)
{
printf("Name : %s \n", p->name);
printf("Date of Birth: %d %d %d\n",
p->year, p->month, p->date);
}
void Person_address_print(Person *p)
{
printf("Name : %s Address %p\n", p->name, &(p->name));
printf("Date of Birth: %d %d %d\n",
p->year, p->month, p->date);
printf("Their address : %p %p %p\n",
&(p->year), &(p->month), &(p->date));
}
int main(int argc, char ** argv)
{
Person * p1 = Person_construct(1989,9, 21, "Amy");
Person_print(p1);
Person * p3 = p1;
p3->name = "echo";
Person_print(p3);
Person_print(p1); // p1's name should have changed to "echo".
Person_address_print(p1);
Person_address_print(p3);
Person_destruct(p1);
// p3 is pointing to the same memory of p1, should not destruct(p3)
return EXIT_SUCCESS;
}
我所在的环境运行
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
valgrind-3.13.0
非常感谢任何线索!
@kaylum 的回答启发了我。
我忘记了 C 的 string literal 概念,如果我做了 p3->name = "echo"
,我手动让 p3->name
指向一个字符串文字和它之前指向的 char 数组,这是 malloc在堆内存中,将丢失。
这就是我在 free(p->name)
;
时失败的原因
谢谢@kaylum!
正在学习C的malloc和自定义结构相关的free heap memory
我遇到的问题
对于下面的代码,我经常得到 segment fault
。
使用 valgrind
分析显示:==12999== Address 0x108b4b is in a r-x mapped file <folder_path> segment
==12999==
完整输出:
Name : Amy
Date of Birth: 1989 9 21
Name : echo
Date of Birth: 1989 9 21
Name : echo
Date of Birth: 1989 9 21
Name : echo Address 0x5580be70e270
Date of Birth: 1989 9 21
Their address : 0x5580be70e260 0x5580be70e264 0x5580be70e268
Name : echo Address 0x5580be70e270
Date of Birth: 1989 9 21
Their address : 0x5580be70e260 0x5580be70e264 0x5580be70e268
free p->name
Segmentation fault (core dumped)
我做的分析
我使用 valgrind
来尝试找到结果:
valgrind --tool=memcheck --leak-check=full ./person2
输出显示为:
Their address : 0x522d040 0x522d044 0x522d048
Name : echo Address 0x522d050
Date of Birth: 1989 9 21
Their address : 0x522d040 0x522d044 0x522d048
free p->name
==12999== Invalid free() / delete / delete[] / realloc()
==12999== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12999== by 0x108894: Person_destruct (person2.c:33)
==12999== by 0x108A2F: main (person2.c:74)
==12999== Address 0x108b4b is in a r-x mapped file /folder/path segment
==12999==
freed p->name
free p
freed p
==12999==
==12999== HEAP SUMMARY:
==12999== in use at exit: 4 bytes in 1 blocks
==12999== total heap usage: 3 allocs, 3 frees, 1,052 bytes allocated
==12999==
==12999== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==12999== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12999== by 0x108817: Person_construct (person2.c:16)
==12999== by 0x1089CC: main (person2.c:64)
==12999==
==12999== LEAK SUMMARY:
==12999== definitely lost: 4 bytes in 1 blocks
==12999== indirectly lost: 0 bytes in 0 blocks
==12999== possibly lost: 0 bytes in 0 blocks
==12999== still reachable: 0 bytes in 0 blocks
==12999== suppressed: 0 bytes in 0 blocks
==12999==
==12999== For counts of detected and suppressed errors, rerun with: -v
==12999== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
我的理解是 *p3
指向与 p1
完全相同的内存片(Person_address_print()
证明了这一点,因此我只是显式地 destruct p1
以避免两次破坏相同的堆内存。)
我还尝试让 p3->name = "ada";
确保分配的字符串仍在之前的长度 (3) 内,或者在调用 Person_destruct(p1)
之前显式设置 p3 == NULL
;发生相同的段错误:(
密码
这是代码。代码基本上是这样的:
一种。自定义一个结构Person
b. (in main
)为Person
构造对象,销毁它们并打印相关属性。
// person.h
#ifndef PERSON_H
#define PERSON_H
typedef struct
{
int year;
int month;
int date;
char * name; // name is a ponter b/c name length is unknown
} Person;
Person * Person_construct(int y, int m, int d, char * n);
void Person_destruct(Person *p);
void Person_print(Person * p);
#endif
#include "person.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Person *Person_construct(int y, int m, int d, char *n)
{
Person *p = NULL;
p = malloc(sizeof (Person));
if (p == NULL) // malloc failed
{
return NULL;
}
p->year= y;
p->month = m;
p->date = d;
p->name = malloc(sizeof(char) * (strlen(n) + 1));
// + 1 for the neding char '[=14=]'
if ((p->name) == NULL)// malloc failed, just return
{
free(p);
return NULL;
}
strcpy(p->name, n);
return p;
}
void Person_destruct(Person *p)
{
// p->name must be freed befoer p is freed
if (p->name != NULL)
{
printf("free p->name \n");
free(p->name);
printf("freed p->name \n");
}
if (p != NULL)
{
printf("free p \n");
free(p);
printf("freed p \n");
}
}
void Person_print(Person *p)
{
printf("Name : %s \n", p->name);
printf("Date of Birth: %d %d %d\n",
p->year, p->month, p->date);
}
void Person_address_print(Person *p)
{
printf("Name : %s Address %p\n", p->name, &(p->name));
printf("Date of Birth: %d %d %d\n",
p->year, p->month, p->date);
printf("Their address : %p %p %p\n",
&(p->year), &(p->month), &(p->date));
}
int main(int argc, char ** argv)
{
Person * p1 = Person_construct(1989,9, 21, "Amy");
Person_print(p1);
Person * p3 = p1;
p3->name = "echo";
Person_print(p3);
Person_print(p1); // p1's name should have changed to "echo".
Person_address_print(p1);
Person_address_print(p3);
Person_destruct(p1);
// p3 is pointing to the same memory of p1, should not destruct(p3)
return EXIT_SUCCESS;
}
我所在的环境运行
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
valgrind-3.13.0
非常感谢任何线索!
@kaylum 的回答启发了我。
我忘记了 C 的 string literal 概念,如果我做了 p3->name = "echo"
,我手动让 p3->name
指向一个字符串文字和它之前指向的 char 数组,这是 malloc在堆内存中,将丢失。
这就是我在 free(p->name)
;
谢谢@kaylum!