c++ - 使用 malloc 而不是 new 导致 free(): invalid pointer 错误
问题描述
出于某种原因,使用 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 和 new 之间的区别
您需要阅读更多关于 C++的内容,例如一些C++ 编程书籍,以及一个好的C++ 参考站点。是的,C++ 是一种非常困难的语言(你需要多年的工作才能掌握它)。稍后,您可以深入了解 C++11 标准n3337(或一些更新的 C++ 标准)。您当然需要准确理解构造函数和析构函数的作用(并解释这需要很多页,远远超过您在任何 StackOverflow 答案中合理预期的内容)。
你需要让你的构造函数的代码被执行(这是用new
但不是用来完成的malloc
) - 稍后也应该在释放内存之前执行析构函数。析构函数由delete
(以及在许多其他情况下)调用,但当然不是由free
. 另请阅读关于五规则和关于RAII的信息。
如果可能,您应该更喜欢使用智能指针。有时(例如对于循环引用)它们是不够的。
害怕未定义的行为。
valgrind工具可用于查找与内存相关的错误。您还应该使用所有警告和调试信息进行编译,因此g++ -Wall -Wextra -g
使用GCC。您可能还想使用静态源代码分析器工具,例如clang-analyzer或Frama-C。使用它们可能需要很多专业知识;没有灵丹妙药。
你struct Record_array
错了:更喜欢使用std::vector<Record>
. 阅读有关标准 C++容器的更多信息。
你的构造函数Record
会调用of的构造函数str1
( str2
即它的构造函数std::string
-s应用于两个不同的位置)。如果您不调用该Record
构造函数,str1
并str2
保持某种未定义状态(因此,一旦使用它们,您就会有一些未定义的行为)。
malloc
& free
(对于 C)和new
and (对于 C++)之间的主要区别在于delete
构造函数和析构函数的参与方式。当然,malloc
&free
忽略它们,但不是new
& delete
。内存分配失败(例如,当虚拟内存耗尽时)也有不同的处理方式。
PS。在实践中,你永远不应该malloc
在 C++ 代码中使用,除非 - 在极少数情况下 - 定义你自己的operator new
. 因为malloc
不调用 C++ 构造函数(但new
确实如此)。另外,请理解C 和 C++ 是不同的编程语言,并且malloc
是针对 C 而不是 C++。许多C++ 标准库实现在其标准实现中使用并 在其.malloc
::operator new
free
::operator delete
推荐阅读
- python - 传递给内核的cupy变量被忽略
- python - 如何在 Python Selenium 中单击此元素?
- hl7-fhir - FHIR:有没有办法在组织中搜索积极从业者?
- twilio - 原始导出 Twilio Studio 执行日志和调试器消息?
- r - 错误:聚类数据时未找到对象“结果”
- json - 通过 ngModel 过滤 JSON
- c++ - 为什么使用 using 声明编译?
- android - 当 minifyEnabled 为 true gradle 时,Multidexing 不起作用
- sql - 如何为 sql db (Apollo Server) 编写 GraphQL 更新突变
- javascript - 如何接受 javascript 的 id?