大家好,
我试图实现一个应该读取二进制文件的函数
在代码中的某一点,我总是会遇到内存访问错误
我已经知道,这是因为我调用某个函数后,我的局部变量的内存地址发生了变化,即使该函数与我的局部变量无关。
愿任何人都能告诉我我做错了什么吗?
这是我的代码:
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cstdint>
//all Blocks from .sum in form of struct
struct HMDSPEC{
int value1;
int value2;
};
struct TIME{
double value;
std::string dimension;
};
struct DATE{
int day;
std::string month;
int year;
};
//global variables
HMDSPEC hmdspec;
TIME scheduledTime;
DATE date;
void EraseSpaces(char* arr,std::string &s) {
for(int i = 0; i < 8 ;i++){
if(std::isspace(arr[i])){
arr[i]='\0';
}
}
s=std::string(arr);
}
void readHMDSPEC(std::ifstream &reader){
std::cout<<"in HMDSPEC -> Adresse von reader : " << &reader << std::endl;
std::cout << &hmdspec<<std::endl;
std::cout << &hmdspec.value1 << std::endl;
std::cout << &hmdspec.value2 << std::endl;
int sizeOfhmdspecBody;
reader.read(reinterpret_cast<char *>(&sizeOfhmdspecBody), 8);
std::cout<<"in HMDSPEC nach 1st lesen-> Adresse von reader : " << &reader << std::endl;
std::cout << &sizeOfhmdspecBody << std::endl;
reader.read(reinterpret_cast<char *>(&hmdspec.value1), sizeOfhmdspecBody/2);
std::cout<<"in HMDSPEC nach 2nd lesen-> Adresse von reader : " << &reader << std::endl;
std::cout << &hmdspec<<std::endl;
std::cout << &hmdspec.value1 << std::endl;
reader.read(reinterpret_cast<char *>(&hmdspec.value2), sizeOfhmdspecBody/2);
std::cout<<"in HMDSPEC nach 3rd lesen-> Adresse von reader : " << &reader << std::endl;
std::cout << &hmdspec.value2 << std::endl;
}
void readTIME(char *word, std::ifstream &reader){
reader.read(word,8);
reader.read(reinterpret_cast<char *>(&scheduledTime.value),8);
reader.read(word, 8);
EraseSpaces(word,scheduledTime.dimension);
}
void RcppReadSumBin(std::string fname)
{
std::ifstream reader(fname,std::ios::binary|std::ios::in);
std::string s;
s.reserve(512);
char word[8];
std::cout<<"Nach deklaration -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach deklaration -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach deklaration -> Adresse von reader : " << &reader << std::endl;
s.reserve(256);
reader.read(word, 8);
std::cout<<"Nach erstem einlesen -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach erstem einlesen -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach erstem einlesen -> Adresse von reader : " << &reader << std::endl;
EraseSpaces(word,s);
std::cout<<"Nach eraseSpaces -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach eraseSpaces -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach eraseSpaces -> Adresse von reader : " << &reader << std::endl;
int i =0;
std::cout<<"Vor while -> Adresse von word : " << &word << std::endl;
std::cout<<"Vor while -> Adresse von s : " << &s << std::endl;
std::cout<<"Vor while -> Adresse von reader : " << &reader << std::endl;
std::cout<<"Vor while -> Adresse von i : " << &i << std::endl;
while(s!="ENDFILE"){
reader.read(word,8);
std::cout<<"Nach nächstem read -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach nächstem read -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach nächstem read -> Adresse von reader : " << &reader << std::endl;
std::cout<<"Nach nächstem read -> Adresse von i : " << &i << std::endl;
EraseSpaces(word,s);
std::cout<<"Nach eraseSpaces -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach eraseSpaces -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach eraseSpaces -> Adresse von reader : " << &reader << std::endl;
std::cout<<"Nach eraseSpaces -> Adresse von i : " << &i << std::endl;
if(s=="HMDSPEC"){
std::cout<<"In HMDSPEC -> Adresse von word : " << &word << std::endl;
std::cout<<"In HMDSPEC -> Adresse von s : " << &s << std::endl;
std::cout<<"In HMDSPEC -> Adresse von reader : " << &reader << std::endl;
std::cout<<"In HMDSPEC -> Adresse von i : " << &i << std::endl;
readHMDSPEC(reader);
std::cout<<"Nach readHMDSPEC -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach readHMDSPEC -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach readHMDSPEC -> Adresse von reader : " << &reader << std::endl;
std::cout<<"Nach readHMDSPEC -> Adresse von i : " << &i << std::endl;
}else if (s=="TIME"){
readTIME(word,reader);
std::cout << scheduledTime.value << std::endl;
std::cout << scheduledTime.dimension << std::endl;
}/*else if (s=="DATE"){
readDATE();
}else if (s=="CELLDATA"){
readCELLDATA();
}else if (s=="CONNDATA"){
readCONNDATA();
}else if (s=="SRCDATA"){
readSRCDATA();
}else if (s=="FPCEDATA"){
readFPCEDATA();
}else if (s=="FPCODATA"){
readFPCODATA();
}*/
std::cout<<"Nach if -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach if -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach if -> Adresse von reader : " << &reader << std::endl;
std::cout<<"Nach if -> Adresse von i : " << &i << std::endl;
i++;
std::cout<<"Nach i++ -> Adresse von word : " << &word << std::endl;
std::cout<<"Nach i++ -> Adresse von s : " << &s << std::endl;
std::cout<<"Nach i++ -> Adresse von reader : " << &reader << std::endl;
std::cout<<"Nach i++ -> Adresse von i : " << &i << std::endl;
}
reader.close();
}
int main ()
{
std::string filename="SPE1.0000.SUM";
RcppReadSumBin(filename);
exit(0);
}
当我打印地址时,它看起来像这样(例如)
在readHDMSPEC之前:
字:0x7ffded9a42b0
s:0x7ffded9a42c0
读者:0x7ffded9a42e0
我:0x7ffded9a42ac
readHDMSPEC之后:
字:0x7ffcfffffdb0
s:0x7ffcfffffdc0
读者:0x7ffcfffffde0
i:0x7ffcfffffdac
谢谢
答案 0 :(得分:5)
这是罪魁祸首:
int sizeOfhmdspecBody;
reader.read(reinterpret_cast<char *>(&sizeOfhmdspecBody), 8);
您正在将{8}字节读入int
,但在大多数(如果不是全部)公共平台上,sizeof(int)
为4.如果您知道数据流中将有8个字节,请使用一个合适的类型,例如std::int64_t
,而不是int
。
答案 1 :(得分:5)
这是一个非常有问题的事情:
int sizeOfhmdspecBody;
reader.read(reinterpret_cast<char *>(&sizeOfhmdspecBody), 8);
我不知道sizeof(int) == 8
的任何平台。即使在64位系统上,int
的大小也是4个字节。这将导致程序写出sizeOfhmdspecBody
变量的界限,导致未定义的行为,使整个程序格式错误。
解决方案?不要使用硬编码的magic numbers。而是使用例如sizeof sizeOfhmdspecBody
为大小。
如果文件中的数据是8字节(64位),则使用int64_t
作为类型,或使用uint8_t
的数组作为正确的大小。
正如Lou Franco在评论中指出的那样,如果sizeOfhmdspecBody
的值不等于sizeof(int)
,那么接下来的两行也会做坏事。
答案 2 :(得分:4)
使用重新解释演员时应该小心。在这段代码中:
int sizeOfhmdspecBody;
reader.read(reinterpret_cast<char *>(&sizeOfhmdspecBody), 8);
你假设,int
是8个字节,但看起来并非如此,你在该变量之后覆盖内存(打破堆栈)。您应该使用int64_t
而不是int
并在您的代码中添加断言语句sizeof(sizeOfhmdspecBody) == 8