【发布时间】:2019-07-31 19:03:05
【问题描述】:
由于某种原因,使用 gcc 编译以下代码并在 Ubuntu 上运行它生成的二进制文件会出现 free(): invalid pointer 错误:
#include <stdlib.h>
#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include <ios>
#include <new>
struct arr_double_size {
double *array;
int size;
};
struct Record {
int ID;
std::string str1;
std::string str2;
int num;
struct arr_double_size values;
};
struct Record_array {
struct Record *array;
int size;
};
void Copy_Read(void) {
std::ifstream file{"in_file"};
std::ofstream new_file{"out_file"};
std::string line;
while (std::getline(file,line)) {
new_file << line << std::endl;
}
file.close();
new_file.close();
}
int main(void) {
Copy_Read();
struct Record rec;
struct arr_double_size values;
values.size = 1;
values.array = (double *)malloc(1 * sizeof(double));
values.array[0] = 72.12;
rec.ID = 2718;
rec.str1 = "Test1";
rec.str2 = "Test2";
rec.num = 1;
rec.values = values;
struct Record_array record_list;
record_list.size = 1;
record_list.array = (struct Record *)malloc(1 * sizeof(struct Record));
record_list.array[0] = rec;
return 0;
}
in_file的内容是:
TEST TEST TEST
奇怪的是,将main 中的调用注释为Copy_Read 可以解决问题,将malloc 的调用替换为new 的调用也是如此。使用 gdb 运行程序显示尝试将rec 分配给record_list.array[0] 时出现错误。为什么会出现这种情况?我试图在这里举一个最小的例子;以前,此代码的扩展版本导致分段错误而不是 free(): invalid pointer 错误。我知道这是一个可怕的代码,永远不应该在严肃的程序中使用(我应该使用标准库 vector 和 new),但似乎有些东西我不明白并且没有很好的记录(无论如何,在初学者可以访问的资源中)关于 malloc 和 new 之间的区别,这是此代码问题的根源。
【问题讨论】:
-
您不能使用
malloc()为包含非原始类型(也称为非 POD 类型)的结构/类分配内存。你的Record结构包含std::string类的字段,如果你使用malloc(),它们的构造函数将不会被正确调用。作为一般建议:不要在 C++ 中使用malloc()/free()或new/delete。请改用适当的容器类型或智能指针。 -
@BasileStarynkevitch 我确实使用您提到的所有选项进行了编译,并且 gcc 保持沉默。我计划进一步了解 valgrind 的使用,但还没有时间这样做。
-
但不足之处在于你对C++的理解和知识。是的,C++ 是一种非常难的编程语言。
-
@flakmonkey -
malloc为用户分配一块内存——句号。它对您的代码一无所知,与您的代码的任何其他方面没有任何交互,并且对任何其他对象的默认构造一无所知。它只是分配一个内存块,成功时返回指向新块的指针,否则返回NULL。相比之下,C++new对应物确实知道正在构造的对象,并且会默认构造一个新对象。这就是为什么 C++ 有new而不是简单的malloc。
标签: c++ segmentation-fault malloc new-operator