无效写入 Valgrind
Invalid Write Valgrind
我正在编写一个函数,它将 Person
插入到指向 Person
的指针数组中,其中 Person
定义为:
typedef struct Person {
char *name;
int age;
} Person;
而我的插入方法是:
static void insert(Person **arr, char *name, int age) {
static int next_free_place = 0;
/* put name and age into the next free place in the array parameter here */
Person *next_person = malloc(sizeof(Person));
if (!next_person) {
fprintf(stderr, "Failed to allocate memory");
exit(-1);
}
next_person->name = name;
next_person->age = age;
*(arr + next_free_place) = next_person; // INVALID WRITE HERE FROM VALGRIND
// move on to next location
next_free_place++;
}
我的主要:
int main(int argc, char **argv) {
/* declare the people array here */
Person **people = NULL;
for (int i = 0; i < HOW_MANY; i++) {
insert(people, names[i], ages[i]);
}
/* print the people array here*/
for (int i = 0; i < HOW_MANY; i++) {
printf("Name: %s, Age: %d\n", people[i]->name, people[i]->age);
}
free(people);
return 0;
}
在头文件中:
#define HOW_MANY 7
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
当我 运行 我的程序时,我得到 Segmentation Fault
并且 Valgrind 显示存在如上所述的无效写入。
我可以知道为什么会发生这种情况以及如何解决吗?
这里的问题是人们没有指向任何地方。您必须静态创建一个数组,或为其分配动态内存。
最初,Person **people = NULL;
。当您调用 insert()
时,**arr
将指向 NULL。
现在,当您执行 *(arr + next_free_place) = next_person;
时,您正在尝试取消引用 NULL 指针,这导致了问题。
解法:
// Static memory - Array of "HOW_MANY" pointers. In this case memory will be
// allocated on stack. It automatically gets freed once the variable goes
// out of scope. No explicit free() is required.
Person *people[HOW_MANY] = {NULL}; //Entire memory is set to 0/NULL automatically
// OR
// Dynamic memory - Allocate memory for "HOW_MANY" pointers.In this case
// memory will be allocated on heap. Explicit free(people); is required.
Person **people = malloc(sizeof(Person*)*HOW_MANY);
if(NULL == people ) {/* handle this case */}
memset(people, 0x00, sizeof(Person*)*HOW_MANY); //You need to reset memory explicitly
对于初学者,您没有为指向 Person 类型的 object 的指针数组分配内存。因此,当您尝试取消引用指针 people(或函数内的 arr)时,程序具有未定义的行为:
*(arr + next_free_place) = next_person;
其次,您还需要为数组中的每个 object 释放所有分配的内存。
考虑到将变量定义放在 header 中是个坏主意。当 header 包含在多个翻译单元中时,这可能会导致链接器错误。您应该在 header 中仅放置变量声明而不使用说明符 extern
定义变量。定义应放在模块中。
这是您更新后的程序。
#include <stdio.h>
#include <stdlib.h>
#define HOW_MANY 7
char *names[HOW_MANY] =
{
"Simon", "Suzie", "Alfred", "Chip", "John", "Tim", "Harriet"
};
unsigned int ages[HOW_MANY]= { 22, 24, 106, 6, 18, 32, 24 };
typedef struct Person
{
const char *name;
unsigned int age;
} Person;
enum RETURN_CODES { Success, Full, NotEnoughMemory };
static int insert( Person **arr, const char *name, unsigned int age )
{
static size_t next_free_place = 0;
if ( next_free_place == HOW_MANY ) return Full;
/* put name and age into the next free place in the array parameter here */
arr[next_free_place] = malloc( sizeof( Person ) );
if ( arr[next_free_place] == NULL ) return NotEnoughMemory;
arr[next_free_place]->name = name;
arr[next_free_place]->age = age;
++next_free_place;
return Success;
}
int main(void)
{
Person **people = calloc( HOW_MANY, sizeof( Person * ) );
for ( int i = 0; i < HOW_MANY; i++ )
{
insert( people, names[i], ages[i] );
}
for ( int i = 0; i < HOW_MANY; i++ )
{
printf( "Name: %s, Age: %u\n", people[i]->name, people[i]->age );
}
for ( int i = 0; i < HOW_MANY; i++ ) free( people[i] );
free( people );
return 0;
}
程序输出为
Name: Simon, Age: 22
Name: Suzie, Age: 24
Name: Alfred, Age: 106
Name: Chip, Age: 6
Name: John, Age: 18
Name: Tim, Age: 32
Name: Harriet, Age: 24
我正在编写一个函数,它将 Person
插入到指向 Person
的指针数组中,其中 Person
定义为:
typedef struct Person {
char *name;
int age;
} Person;
而我的插入方法是:
static void insert(Person **arr, char *name, int age) {
static int next_free_place = 0;
/* put name and age into the next free place in the array parameter here */
Person *next_person = malloc(sizeof(Person));
if (!next_person) {
fprintf(stderr, "Failed to allocate memory");
exit(-1);
}
next_person->name = name;
next_person->age = age;
*(arr + next_free_place) = next_person; // INVALID WRITE HERE FROM VALGRIND
// move on to next location
next_free_place++;
}
我的主要:
int main(int argc, char **argv) {
/* declare the people array here */
Person **people = NULL;
for (int i = 0; i < HOW_MANY; i++) {
insert(people, names[i], ages[i]);
}
/* print the people array here*/
for (int i = 0; i < HOW_MANY; i++) {
printf("Name: %s, Age: %d\n", people[i]->name, people[i]->age);
}
free(people);
return 0;
}
在头文件中:
#define HOW_MANY 7
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
当我 运行 我的程序时,我得到 Segmentation Fault
并且 Valgrind 显示存在如上所述的无效写入。
我可以知道为什么会发生这种情况以及如何解决吗?
这里的问题是人们没有指向任何地方。您必须静态创建一个数组,或为其分配动态内存。
最初,Person **people = NULL;
。当您调用 insert()
时,**arr
将指向 NULL。
现在,当您执行 *(arr + next_free_place) = next_person;
时,您正在尝试取消引用 NULL 指针,这导致了问题。
解法:
// Static memory - Array of "HOW_MANY" pointers. In this case memory will be
// allocated on stack. It automatically gets freed once the variable goes
// out of scope. No explicit free() is required.
Person *people[HOW_MANY] = {NULL}; //Entire memory is set to 0/NULL automatically
// OR
// Dynamic memory - Allocate memory for "HOW_MANY" pointers.In this case
// memory will be allocated on heap. Explicit free(people); is required.
Person **people = malloc(sizeof(Person*)*HOW_MANY);
if(NULL == people ) {/* handle this case */}
memset(people, 0x00, sizeof(Person*)*HOW_MANY); //You need to reset memory explicitly
对于初学者,您没有为指向 Person 类型的 object 的指针数组分配内存。因此,当您尝试取消引用指针 people(或函数内的 arr)时,程序具有未定义的行为:
*(arr + next_free_place) = next_person;
其次,您还需要为数组中的每个 object 释放所有分配的内存。
考虑到将变量定义放在 header 中是个坏主意。当 header 包含在多个翻译单元中时,这可能会导致链接器错误。您应该在 header 中仅放置变量声明而不使用说明符 extern
定义变量。定义应放在模块中。
这是您更新后的程序。
#include <stdio.h>
#include <stdlib.h>
#define HOW_MANY 7
char *names[HOW_MANY] =
{
"Simon", "Suzie", "Alfred", "Chip", "John", "Tim", "Harriet"
};
unsigned int ages[HOW_MANY]= { 22, 24, 106, 6, 18, 32, 24 };
typedef struct Person
{
const char *name;
unsigned int age;
} Person;
enum RETURN_CODES { Success, Full, NotEnoughMemory };
static int insert( Person **arr, const char *name, unsigned int age )
{
static size_t next_free_place = 0;
if ( next_free_place == HOW_MANY ) return Full;
/* put name and age into the next free place in the array parameter here */
arr[next_free_place] = malloc( sizeof( Person ) );
if ( arr[next_free_place] == NULL ) return NotEnoughMemory;
arr[next_free_place]->name = name;
arr[next_free_place]->age = age;
++next_free_place;
return Success;
}
int main(void)
{
Person **people = calloc( HOW_MANY, sizeof( Person * ) );
for ( int i = 0; i < HOW_MANY; i++ )
{
insert( people, names[i], ages[i] );
}
for ( int i = 0; i < HOW_MANY; i++ )
{
printf( "Name: %s, Age: %u\n", people[i]->name, people[i]->age );
}
for ( int i = 0; i < HOW_MANY; i++ ) free( people[i] );
free( people );
return 0;
}
程序输出为
Name: Simon, Age: 22
Name: Suzie, Age: 24
Name: Alfred, Age: 106
Name: Chip, Age: 6
Name: John, Age: 18
Name: Tim, Age: 32
Name: Harriet, Age: 24