使用malloc而不是new会导致free():指针错误无效

问题描述 投票:-4回答:1

出于某种原因,使用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错误。我知道这是一个可怕的代码,永远不应该在一个严肃的程序中使用(我应该使用标准库vectornew),但似乎有一些我不理解的东西,并没有很好的文档记录(在资源可访问对于初学者,无论如何)关于mallocnew之间的区别,这是该代码问题的根源。

c++ segmentation-fault malloc new-operator
1个回答
0
投票

我不明白malloc和new之间的区别

你需要阅读更多关于C ++的内容,例如:一些C++ programming书,和一个很好的C++ reference网站。是的,C ++是一门非常困难的语言(你需要多年的工作来掌握它)。稍后,您可以深入研究C ++ 11标准n3337(或更新的C ++标准)。你当然需要准确理解constructorsdestructors的作用(并解释这需要很多页面,远远超过你在任何StackOverflow答案中可以合理预期的内容)。

您需要执行constructors的代码(使用new但不能使用malloc) - 稍后在释放内存之前还应执行析构函数。析构函数由delete(以及许多其他情况)调用,但当然不是由free调用。阅读有关rule of fiveRAII的信息。

你应该尽可能使用smart pointers。有时(例如,对于循环引用),它们是不够的。

害怕undefined behavior

valgrind工具可用于捕获与内存相关的错误。您还应编译所有警告和调试信息,所以g++ -Wall -Wextra -gGCC。您可能还想使用静态源代码分析工具,如clang-analyzerFrama-C。使用它们可能需要大量的专业知识;有no silver bullet

你的struct Record_array错了:更喜欢使用std::vector<Record>。阅读有关标准C ++ containers的更多信息。

你的Record的构造函数将调用str1str2的构造函数(它,std::string-s的构造函数应用于两个不同的位置)。如果你不调用那个Record构造函数,str1str2会保持一些未定义的状态(所以你使用它们就会有一些undefined behavior)。

mallocfree(对于C)和newdelete(对于C ++)的主要区别在于构造函数和析构函数的参与方式。当然,mallocfree忽略了它们,但不是newdelete。存储器分配的失败(例如,当虚拟存储器耗尽时)也以不同方式处理。

PS。在实践中,你不应该在C ++代码中使用malloc,除非 - 仅在极少数情况下 - 定义自己的operator new时。因为malloc不会调用C ++构造函数(但new会这样做)。另外,请理解C和C ++是不同的编程语言,malloc是C语言,而不是C ++。许多C++ standard library实现在他们的标准malloc的实现中使用::operator new并在他们的free中使用::operator delete

© www.soinside.com 2019 - 2024. All rights reserved.