本帖最后由 ancientcc 于 2017-2-21 09:25 编辑 要判断std::istream长度,一般是用以下代码。in是std::istream对象。
但in是preprocess_file返回的对象时,值是-1!原因是这个istream不是通常意义上磁盘文件,它的长度要随着不断std::istream::get而增长。具体表现在要get时,会问是否还有可读数据,此时就会调用underflow,如果有数据就被从preprocessor_data取出来,——如此循环,直到preprocessor_data没数据了。 当然,tellg可安全计算磁盘文件的长度。 |
本帖最后由 ancientcc 于 2017-2-21 09:49 编辑 这里以读取D:\Program Files\Battle for Wesnoth 1.6.1\data\hardwired\fonts.cfg为例来作具体说明。 fonts.cfg:文件大小,23,149 字节 1、preprocess_file执行到了new preprocessor_file(*buf, callstack, fname), @buf,一个指向preprocessor_streambuf对像的指针; @fname:D:\Program Files\Battle for Wesnoth 1.6.1\data\hardwired\fonts.cfg; 2、new操作从堆出申请出sizeof(preprocessor_file)大小的内存块,内存块地址:0x1d49660 3、new操作开始执行preprocessor_file构造函数。 3.1、执行构造函数时首先执行其父类preprocessor的构造函数,注意这构造函数执行后一些成员的值: old_preprocessor_: 0x00000000 target_.depth_ = 1 target_.current = 0x1d49660(此次分配的processor_file) 3.2、判断出name是文件,于是执行new preprocessor_data(t, called_macros_, file_stream, "", name, 1, directory_name(name), t.textdomain_) 3.2.1、new操作从堆出申请出sizeof(preprocessor_data)大小的内存块,内存块地址:0x1d49858 3.2.2、new操作开始执行preprocessor_data构造函数。 3.2.2.1、执行构造函数时首先执行其父类preprocessor的构造函数,注意这构造函数执行后一些成员的值: old_preprocessor_: 0x1d49660, 也即以上的processor_file target_.depth_ = 2 target_.current = 0x1d49858(此次分配的processor_data) 注:processor_file和processor_data中的target是同一个,其值就是那个指向preprocessor_streambuf对像的指针,buf 4、程序开始读取数据,istream.get()调用preprocessor_streambuf::underflow(),underflow以着每一次2459字节向上送(>2000),这样读了9次后,最后一次只剩下了325字节(这个数字不等于23,149 - 2459*9 = 1018,为什么需要再解释,但不是这里要涉及的。!!!!!while (current_ && (in_avail = buffer_.rdbuf()->in_avail()) < desired_fill_amount), in_avail被变掉,217-->325!!(当然会变,上次没有把最后一次的current->get_chunk计算在内)。每次读取时underflow一些数值: 1th: current_: 0x1d49858, 2459 2th: current_: 0x1d49858, 2459 3th: current_: 0x1d49858, 2459 4th: current_: 0x1d49858, 2459 5th: current_: 0x1d49858, 2459 6th: current_: 0x1d49858, 2459 7th: current_: 0x1d49858, 2459 8th: current_: 0x1d49858, 2459 9th: current_: 0x1d49858, 2459 10th: current_: 0x1d49858, 325 5、在最后一次读时,current_->get_chunk()返回flase,至此开始调用delete current_。 5.1、这个current_指向preprocessor_data,delete析构preprocessor_data,析构了自己后去折构父类preprocessor,即调用preprocessor::~preprocessor(),该函数执行后注意几个变量值: target_.current_ = old_preprocessor_ = 0x1d49660; --target_.depth_ = --2 = 1; 经过这么个析构,preprocessor_streambuf中的current_被换到了0x1d49660,即指向preprocessor_file那个 6、underflow执行current_->get_chunk,processor_file::get_chunk执行时pos_ == end_,不执行任何操作就返回false,至此又一次调用delete current_(这次是processor_file的了) 6.1、这个current_指向preprocessor_file,delete析构preprocessor_file,析构了自己后去折构父类preprocessor,即调用preprocessor::~preprocessor(),该函数执行后注意几个变量值: old_preprocessor_: 0x00000000 target_.depth_ = --1 = 0 target_.current = 0x00000000这个target_就是那个指向preprocessor_streambuf对像的指针,buf 到此delete current_在析构掉自己同时把current_也给置null了! |
STL,例如istream::get(),会在读#out_buffer_到结末时调用这函数 函数主要执行,1)调用#current_把数据放入#buffer_,2)#buffer_数据复制向#out_buffer。 返回值是#out_buffer_的第一个有效数据值 这函数存在一处较难理解地方,
|